PAT A1033 To Fill or Not to Fill (25分)甲级题解

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: C​max​​ (≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; D​avg​​ (≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: P​i​​, the unit gas price, and D​i​​ (≤D), the distance between this station and Hangzhou, for i=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

题解思路:
这题是一道贪心算法题,贪心和动态规划做题不同的点在于动态规划面向全局最优而贪心算法是面向局部最优解,也就是说贪心算法得出的答案未必是真正完全的最优解,只是在每一个局部最优解的集合,这题的题意就是给你几个加油站的站点,给定油箱容量Cmax以及每升油箱可走的路程数P,然后要求找到最便宜的加油方式到达目的地,首先本题我的做法是初始站点在数组保存的时候从下标1开始,所以0号数组就用不到了,然后第N+1号位置设置为目的站点,然后开始按照距离排序,并且为了题目需要,将第N+1数组位置终点站里的价格设置为-1最小,这里你可以自行理解一下,因为要让价格总和最小,思考的方式就有如下几种:
1.当前所处站点gas[i]最大可走距离内(例子中最大距离为Cmax*p=50*12=600)有加油站的价格比当前加油站gas[i]的价格还要便宜时:
1)如果油箱里剩余的油够走到目的地,那就直接走到目的站点即可不用加油
2)如果油箱里的油不够走到目的地,那就加油加到刚刚好可以到目的加油站即可

2.当前所处站点gas[i]最大可走距离内找不到一个加油站价格比当前加油站价格还要便宜时:
如果当前加油站就是油价最便宜的站点时,就将油箱加满,并且走到最大可走范围内油价最低的加油站,这样能够使得局部范围情况下走到目的加油站所花费的油价最低,(这里可以画图自己理解一下)贪心算法的局部最优性。
这题其实有很多变种类型的题目,还有采用动态规划做要求做到全局情况下最优解的方式,总的说本题算是降低难度了,tips:学习算法要动动手画画图。

注意:当第一个加油站距离不为0的时候要直接输出结束,这是隐藏点。

代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N=520;
const int INF=(1<<30)-1;
struct Gas {
	double dis;
	double price;
} gas[N];
double Cmax,ed;
int perU,n;

bool cmp(Gas a,Gas b) {
	return a.dis<b.dis;
}

int main() {
	cin.tie(0);
	cin>>Cmax>>ed>>perU>>n;
	gas[n+1].dis=ed;
	gas[n+1].price=-1;//设置终点站
	gas[0].dis=-1;
	for(int i=1; i<=n; i++) {
		cin>>gas[i].price>>gas[i].dis;
	}
	sort(gas,gas+n+1,cmp);
	if(gas[1].dis!=0) {
//当第一个加油站距离不为0的时候汽车不可以加油直接结束
		printf("The maximum travel distance = 0.00");
		return 0;
	}
	int maxDis=perU*Cmax,i=1;
	double restOil=0,need=0,cost=0,ans;
	bool tag=true;
	while(i<=n+1) {
		int idx=i+1,cheap;//将最便宜的站点初始值设置为本站点的下一站点
		double minPrice=INF;
		if(idx<=n+1&&(gas[idx].dis-gas[i].dis)>maxDis) {
			ans=gas[i].dis+maxDis;
			tag=false;
			break;
		}
		while(idx<=n+1&&(gas[idx].dis-gas[i].dis)<=maxDis) {//走到终点或者找到最便宜的站点的时候进行退出
			if(gas[idx].price<minPrice) {
				minPrice=gas[idx].price;
				cheap=idx;
				if(gas[cheap].price<gas[i].price) break;//如果找得到比起始站点更加便宜的加油站
			}
			idx++;
		}
		if(i>=n+1) break;
		//找到最便宜的站点了
		if(gas[i].price<gas[cheap].price) {//当前站点就是最便宜的站点的时候加满油 走到最大范围内油价最便宜的站点
			cost+=(Cmax-restOil)*gas[i].price;
			restOil=Cmax-((gas[cheap].dis-gas[i].dis)/perU);
		} else {//找到最便宜的站点了 两个情况 到达目的站油够用 则不加 若不够则加到刚好到目的站的油
			if(((gas[cheap].dis-gas[i].dis)*1.0/perU)<=restOil) {
				restOil-=(gas[cheap].dis-gas[i].dis)*1.0/perU;
			} else {
				cost+=((gas[cheap].dis-gas[i].dis)*1.0/perU-restOil)*gas[i].price;
				restOil=0;
			}
		}
		i=cheap;
	}
	if(tag)
		printf("%.2f",cost);
	else printf("The maximum travel distance = %.2f",ans);
	return 0;
}
posted @ 2021-01-21 21:10  coderJ_ONE  阅读(146)  评论(0)    收藏  举报