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: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=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: Pi, the unit gas price, and Di (<=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
解题思路:贪心思想,对任意一个加油站而言,是否加油由它上一个加油的加油站决定,而加多少由它下一个加油的地方决定。
这么考虑,假设要在第i个加油站,那么加的油只要能到达下一个油价比他的加油站即可(中间经过的加油站都无视即可),如果在加满油的情况下,仍不能到达下一个油价比他低的加油站,那么就在i加油站加满,同时要在i处加满油的情况下所能走的这一段距离中最便宜的加油站进行补充。
这样子,我们每次对第i个节点遍历的时候,确定了i处加的油量以及下一个需要加油的加油站。从起点开始,我们很容易确定,起点是一定要加油的,也就是第一个加油的点。这里我加入了一个虚拟的加油站(位置:终点处;油价:0)。
另一点注意可能同一个地方两个加油站,我们在比较dis[i]~dis[i]+max的过程中将同一位置的加油站按照价格依次排序
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct{
float dis, price;
}gas;
int cmp(gas a, gas b){
return a.dis != b.dis ? a.dis < b.dis : a.price < b.price;
}
float cmax, target, avg, ans = 0, tank = 0, Distance = 0, lastprice, step;
//step记录油箱全满的状态能走多远,tank记录油箱的油量,Distance记录当前的距离,lastprice记录上一个加油的地方的油价。
int n, cur = 1;
int main(){
scanf("%f %f %f %d",&cmax, &target, &avg, &n);
vector<gas>gases(n);
for(int i = 0; i < n; ++ i)
scanf("%f %f",&gases[i].price, &gases[i].dis);
gases.push_back({target, 0.0});
sort(gases.begin(), gases.end(), cmp);
//判断一下能否上路
if(gases[0].dis > 0){
printf("The maximum travel distance = 0.00");
return 0;
}
lastprice = gases[0].price;
step = avg * cmax;
while(Distance < target){
int minid = -1, flag = 0;
float minn = 999999999;
for(; cur <= n && gases[cur].dis <= Distance + step; ++ cur){
if(gases[cur].price < minn){
minn = gases[cur].price;
minid = cur;
}
if(gases[cur].price < lastprice){
flag = 1;
break;
}
}
//最远距离加上step
if(minid == -1){
printf("The maximum travel distance = %.2f", Distance + step);
return 0;
}
//找到一个油价比之前的低的加油站
if(flag == 1){
float need = (gases[cur].dis - Distance) / avg - tank;
ans += lastprice * need;
tank = 0;
}
//没找到比之前低的,就在这段距离中找到相对最低的那个加油站补充一下能量
else{
cur = minid;
float need = cmax - tank;
ans += lastprice * need;
tank = cmax - (gases[cur].dis - Distance) / avg;
}
lastprice = gases[cur].price;
Distance = gases[cur].dis;
++ cur;
}
printf("%.2f",ans);
}