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
题目大意
这题说一辆车从杭州出发,一路上有很多加油站,然后给出这辆车的油箱容量、目的地距离杭州的距离、每升汽油能走的平均距离、还有加油站的个数,然后再输入每个加油站距离杭州的距离以及每个加油站的油价,要求输出到达目的地的最小花费,如果无法到达,则输出汽车最远能走多远。
个人思路
这题是贪心算法的应用,如果不够贪的话很可能没有办法达到最优解,下面给出贪心思路。
- 寻找目标加油站:在某个加油站时,寻找假设在这个加油站加满油的最大行程内,第一个油价比当前加油站小的加油站,如果没有则找到最大行程内油价最低的加油站,将找到的这个加油站设为下一个要抵达的目标加油站。
- 如果目标加油站的油价比当前加油站的油价高,则判断当前加油站能否在最大行程内到达终点,如果可以到达则输出总话费结束程序,如果无法到达,就把油加满。【把油加满的原因是如果不加满那么在目标加油站加油就更贵了】
- 如果目标加油站的油价比当前加油站的油价低,那么就判断能够直接到达目标加油站,如果到达不了就把油加到刚刚好到达目标加油站。
- 找不到目标加油站时,说明要么当前加油站后面没有加油站了,要么后面的加油站到达不了,所以判断是否能到达终点,并输出结果即可。
除了贪心思路外,本题还有一个坑,就是有可能起点不存在加油站,因为初始的油量为0,如果没有初始点的加油站,那么直接输出结果并return结束程序即可。
代码实现
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
struct Station {
double p, d;
};
Station stations[505];
bool cmp(Station s1, Station s2) {
return s1.d < s2.d;
}
int main() {
double rank, d, d_avg;
int n;
// 输入
cin >> rank >> d >> d_avg >> n;
for (int i = 0; i < n; i ++) {
cin >> stations[i].p >> stations[i].d;
}
// 排序
sort(stations, stations+n, cmp);
// 如果起始点没有加油站,则直接输出并结束程序
if (stations[0].d != 0) {
printf("The maximum travel distance = 0.00");
return 0;
}
double ans = 0;
double one_dis = rank * d_avg; // 满油能走的最长距离
double current_rank = 0; // 记录当前剩余油量
int pos = 0; // 记录当前在的加油站的编号
while (1) {
int target = pos; // 记录下个要到达的加油站索引号
double tmp = stations[pos+1].p; // 记录最小油价
double farrest = current_rank * d_avg + stations[pos].d; // 记录当前油量能走到的最大距离
// 寻找到行程内比当前加油站油价低的第一个加油站,如果找不到,就找油价最低的加油站
for (int i = pos+1; i < n; i ++) {
if (stations[i].d > stations[pos].d+one_dis) break;
if (stations[i].p < stations[pos].p) {
target = i;
break;
}
if (stations[i].p <= tmp) {
target = i;
tmp = stations[i].p;
}
}
// 如果当前加油站后面没有加油站或者后面的加油站到达不了
if (target == pos) {
// 能到达终点
if (stations[pos].d + one_dis >= d) {
if (farrest < d) {
ans += stations[pos].p * (d-farrest) / d_avg;
}
printf("%.2lf\n",ans);
}
// 不能到达终点
else {
printf("The maximum travel distance = %.2lf", stations[pos].d+one_dis);
}
break;
}
// 如果目标加油站的油价比当前加油站油价高
if (stations[target].p >= stations[pos].p) {
if (stations[pos].d + one_dis >= d) {
if (farrest < d) {
ans += stations[pos].p * (d-farrest) / d_avg;
}
printf("%.2lf\n",ans);
break;
}
else {
ans += stations[pos].p * (rank-current_rank);
current_rank = rank - (stations[target].d-stations[pos].d) / d_avg;
pos = target;
}
}
// 其他情况进入下一个加油站
else {
if (farrest < stations[target].d) {
ans += stations[pos].p * (stations[target].d-farrest) / d_avg;
current_rank += (stations[target].d-farrest) / d_avg;
}
current_rank -= (stations[target].d-stations[pos].d) / d_avg;
pos = target;
}
}
return 0;
}
总结
学习不息,继续加油
这题的贪心真的蛮复杂的,修改了好几次,贪心正确了,然后发现竟然还有坑,加油加油!