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 }