PAT A1033To Fill or Not to Fill (C++) 贪心,思路清晰易懂

Posted 进击的alphaCat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT A1033To Fill or Not to Fill (C++) 贪心,思路清晰易懂相关的知识,希望对你有一定的参考价值。

题目来源:

【PAT A1033】To Fill or Not to Fill


题目

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive numbers: CmaxC_maxCmax (≤\\le 100), the maximum capacity of the tank; DDD (≤\\le30000), the distance between Hangzhou and the destination city; DavgD_avgDavg (≤\\le20), the average distance per unit gas that the car can run; and NNN (≤\\le 500), the total number of gas stations. Then NNN lines follow, each contains a pair of non-negative numbers: PiP_iPi, the unit gas price, and DiD_iDi (≤D\\le DD), the distance between this station and Hangzhou, for i=1,⋯ ,Ni=1,\\cdots ,Ni=1,,N. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

Sample Input 1:

50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300

Sample Output 1:

749.17

Sample Input 2:

50 1300 12 2
7.10 0
7.00 600

Sample Output 2:

The maximum travel distance = 1200.00

这道题的贪心思路:
每次找比当前更便宜的第一个加油站,如果找到了,就适度加油,刚好开到那里;
如果当前就是最便宜的,则加满油,去找能开到的区间内的最便宜的油站,开到那里。

代码里有一个小trick,就是将终点站也看做一个加油站,收费为0,距离为distance(参考了柳神的思路)。另外,为了方便管理变量,代码组织上加入了面向对象的思想,把汽车有关的变量放到了结构体 drive_state 中。

// 伪代码
while 没有到达终点
	next = 查找下一个油站
	if 当前就是最便宜 :
		判断能否到下一站
		if yes : 
			next = 查找区间内最便宜的站
			加满油,更新花费,位置
		else 退出
	else 
		适度加油,更新花费,位置
		
判断,输出	
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

struct GasStation

    double unit_price,distance;
;

struct drive_state

    double cap,cost;
    int pos;
    double max_dis;
; 

bool cmp(const GasStation &g1, const GasStation &g2)
    return g1.distance < g2.distance;


int find_next_pos(const drive_state &state,const vector<GasStation> &gasStation,int flag)

	if (flag==0) 
	
	    // 找到区间内第一个比当前便宜的油站
	    for ( int i = state.pos+1; i < gasStation.size() && gasStation[i].distance-gasStation[state.pos].distance <= state.max_dis; ++i ) 
	        if (gasStation[i].unit_price <= gasStation[state.pos].unit_price ) return i;
	    
	    return state.pos;
	 
	 else 
	 
	 	// 找区间内最便宜的加油站
	    int min_i = state.pos+1;
	    for ( int i = state.pos+2; i < gasStation.size() && gasStation[i].distance-gasStation[state.pos].distance <= state.max_dis; ++i ) 
	        if (gasStation[i].unit_price <= gasStation[min_i].unit_price ) min_i = i;
	    
	    return min_i;
	


int main()

    double capacity, distance,d_avg;
    int N;
    std::cin >> capacity >> distance >> d_avg >> N;
    vector<GasStation> gasStation(N+1);
    gasStation[N] = 0.0,distance;		// 将终点视为收费为0的加油站(参考柳神思路)
    for ( int i = 0; i!=N;++i) scanf("%lf %lf",&gasStation[i].unit_price,&gasStation[i].distance);
    std::sort(gasStation.begin(),gasStation.end(),cmp);
    // 特殊点判断
    if (gasStation[0].distance > 0 ) 
        printf("The maximum travel distance = 0.00\\n");
        return 0;
    
    
    // 行程开始
    drive_state state = 0,0,0,0;  // 务必初始化!!
    state.max_dis = capacity * d_avg;	// 满油车能开的最远距离
    while (state.pos != N ) 
        int next = find_next_pos(state,gasStation,0);
        // 当前位置是最便宜的,就准备选第二便宜的
        if (next == state.pos) 
        	// 如果跑不到下一站(也就跑不到第二便宜的站),就可以break了
            if (gasStation[state.pos].distance+state.max_dis<gasStation[state.pos+1].distance) break;
            // 否则,在当前站加满油,开到第二便宜的站
            next = find_next_pos(state,gasStation,1);
            state.cost += (capacity - state.cap) * gasStation[state.pos].unit_price;
            state.cap = capacity - (gasStation[next].distance-gasStation[state.pos].distance) / d_avg;
            state.pos = next;
         else 
        // 当前站不是最便宜的,那就把油加到 第一个比当前站便宜的油站即可
            state.cost += ((gasStation[next].distance - gasStation[state.pos].distance) / d_avg - state.cap) * gasStation[state.pos].unit_price;
            state.pos = next;
            state.cap = 0;
        
    
    
    if (state.pos == N ) printf("%.2lf\\n",state.cost);
    else printf("The maximum travel distance = %.2lf\\n",gasStation[state.pos].distance+state.max_dis);

ps:一位室友用递归的方法A掉了这道题,大家有兴趣可以try一try递归的解法。

以上是关于PAT A1033To Fill or Not to Fill (C++) 贪心,思路清晰易懂的主要内容,如果未能解决你的问题,请参考以下文章

PAT 1033. To Fill or Not to Fill

PAT 1004 To Fill or Not to Fill (25)

PAT 1033 To Fill or Not to Fill[dp]

PAT Advanced 1033 To Fill or Not to Fill (25) [贪?算法]

PAT (Advanced Level) 1033. To Fill or Not to Fill (25)

PAT甲级1033 To Fill or Not to Fill (贪心算法)