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 (≤), the distance between this station and Hangzhou, for ,. 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
解题思路:
步骤1:把终点视为单位油价为0、离起点距离为D的加油站,然后将所有加油站按离起点的距离从小到大进行排序。排序完毕后,如果离起点最近的加油站的距离不是0,则表示汽车无法出发(初始时刻油量为0),输出“The maximum travel distance = 0.00”;如果离起点最近的加油站的距离是0(即加油站就在起点),则进入步骤2。
步骤2:假设当前所处的加油站编号为now,接下来将从满油状态下能到达的所有加油站中选出下一个前往的加油站,策略如下:
①寻找距离当前加油站最近的油价低于当前油价的加油站(记为k),加恰好能够到达加油站k的油,然后前往加油站k(即优先前往更低油价的加油站)。
②如果找不到油价低于当前油价的加油站,则寻找油价最低的加油站,在当前加油站加满油,然后前往加油站k(即在没有更低油价的加油站时,前往油价尽可能低的加油站)。
③如果在满油状态下都找不到能到达的加油站,则最远能到达的距离为当前加油站的距离加上满油状态下能前进的距离,结束算法(即没有加油站可以到达时结束算法)。
上面的策略当满足条件③、或者到达加油站n(即终点)时结束。其中①和②的证明如下。策略①的证明:假设三个加油站的顺序为a、b、c(当前在加油站a),且油价大小为a > b(与c的油价大小无关),则先从a加能到达b的油,然后在b加能到达c的油,要比直接从a加能到达c的油要节省(因为a的油价比b高)。因此,在所有能到达的加油站中,总是优先选择最近的油价低于当前油价的加油站。
策略②的证明:假设三个加油站的顺序为a、b、c(当前在加油站a),且油价大小为a <
b < c,显然应该先在a加满油(因为b、c油价高),然后前往b、c中油价较低的加油站b(如果一定要去c,也应该是先到油价相对便宜的b,然后去c才更划算(从c出发买油价格高,还不如在b先买好))。
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 6 int main() 7 { 8 9 int N; 10 double C, D, Dav, dis, price; 11 cin >> C >> D >> Dav >> N; 12 vector<pair<double, double>>station; 13 for (int i = 0; i < N; ++i) 14 { 15 cin >> price >> dis; 16 station.push_back(make_pair(dis, price)); 17 } 18 station.push_back(make_pair(D, 0));//将终点也视为一个加油目的地 19 sort(station.begin(), station.end(), [](pair<int, double>a, pair<int, double>b) {return a.first < b.first; }); 20 if (station[0].first != 0)//起始点没有加油站 21 printf("The maximum travel distance = 0.00\n"); 22 else 23 { 24 int start = 0;//出发点 25 double res = 0.0, nowTank = 0.0; 26 while (start < station.size()) 27 { 28 int next = -1; 29 double minPrice = 10000; 30 for (int i = start + 1; i < station.size() && station[i].first - station[start].first <= C * Dav; ++i)//找到下一家最便宜的加油站 31 { 32 if (minPrice > station[i].second)//没有比当前更便宜的加油站,那就找中途最便宜的加油站 33 { 34 minPrice = station[i].second; 35 next = i; 36 if (station[i].second < station[start].second)//找到比当前便宜点的加油站 37 break; 38 } 39 40 } 41 if (next == -1)//加油站太远,到不到 42 break; 43 double need = (station[next].first - station[start].first) / Dav;//需要耗油量 44 if (minPrice < station[start].second)//比当前油价还便宜,那就不用加满油箱 45 { 46 if (nowTank < need)//油不够 47 { 48 res += station[start].second *(need - nowTank); 49 nowTank = 0;//油刚好到下一站,到达下一站即没有油了 50 } 51 else 52 nowTank -= need;//油还够,那就不用加了 53 } 54 else//中间的加油价比现在的要贵,那就在这里加满 55 { 56 res += station[start].second * (C - nowTank); 57 nowTank = C - need; 58 } 59 start = next; 60 } 61 if (start == N)//到达终点 62 printf("%.2f\n", res); 63 else 64 printf("The maximum travel distance = %.2f\n", station[start].first + C * Dav); 65 } 66 return 0; 67 }