这是一道比较经典的贪心+模拟。
首先说一下大致思路吧:
贪心的关键是要考虑到两种情况:
遍历从当前油站的下一个油站 到 可以到达的最后一个油站:
1、如果碰到油站价格比当前油站价格低,那么就直接退出循环(我们记这个油站为下一个油站),此时在当前油站加的油量应该为(当前油站到下一个油站的距离 - remaining)所需要的油量。(remaining下面一种情况会解释它是什么意思)
2、如果没有比当前油站价格更低的,那么就选择一个相对较低的(下面还是一样称呼它为下一个油站),此时应该加的油量计算方式就大不相同了,这时候应该加满,具体也就是(Cmax*Davg - remaing)这么长的路程所需要的油量。然后更新remaining,remaing的意思就是从当前油站走到下一个油站之后还可以走多远。
Note:remaining只在一种情况下会产生,就是从当前油站可达的其他油站价格中没有比当前的价格更小的,按照贪心的想法,我肯定要在便宜的地方多拿一点。!!!remaining仅仅会影响下一个要去的油站所要加的油量,考虑到这样一个事实,下下一个油站是不可达的,到了下一个油站之后,我们便会将remaining清零(无论是第一种情况还是第二种情况),第二种会先清零再更新。
坑点:1、有一种情况是起点没有油站,所以最大可达就是0。
2、要考虑可能有很多油站在某一个相同的距离处。
3、边界的处理,如果从当前油站可以直接到终点,且中途没有比它价格更低的,那么就直接退出循环,具体可见代码。
#include<bits/stdc++.h>
using namespace std;
bool compare(pair<double, double>& a, pair<double, double>& b) {
if (a.second == b.second) {
return a.first < b.first;
}
return a.second < b.second;
}
int main() {
double Cmax, D, Davg;
int N;
cin >> Cmax >> D >> Davg >> N;
vector<pair<double, double>> stationInfo(N); // first is price, second is distance
for (int i = 0; i<N; ++i) {
cin >> stationInfo[i].first >> stationInfo[i].second;
}
sort(stationInfo.begin(), stationInfo.end(), compare);
if(stationInfo[0].second != 0) {//坑点:有可能第一个油站不在起点
printf("The maximum travel distance = 0.00");
return 0;
}
int curPos = 0;
double ans = 0;
int maxReach = Cmax * Davg;
int reachable = 0;
int remaining = 0;
while (curPos < N) {
double minP = 2 << 20;
int index;
int nextPos = 0;
int flag = 0;
int i;
for (i = curPos + 1; i < N && stationInfo[i].second <= stationInfo[curPos].second + maxReach; ++i) {
flag = 1;
if (stationInfo[i].second == stationInfo[curPos].second)
continue;
if (stationInfo[i].first < stationInfo[curPos].first) {
nextPos = i;
break;
}
if (stationInfo[i].first < minP) {
minP = stationInfo[i].first;
index = i;
}
}
if (i == N) {
if (stationInfo[curPos].second + maxReach >= D) {
break;
}
}
if (!flag)break;
int f = 1;
if (!nextPos) {
f = 0;
nextPos = index;
}
if (f) {
ans += (stationInfo[nextPos].second - stationInfo[curPos].second - remaining) / Davg * stationInfo[curPos].first;
remaining = 0;
}
else {
ans += (maxReach - remaining) / Davg * stationInfo[curPos].first;
remaining = 0;
remaining += maxReach - (stationInfo[nextPos].second - stationInfo[curPos].second);
}
reachable = stationInfo[nextPos].second;
curPos = nextPos;
}
if (reachable + maxReach < D) {
printf("The maximum travel distance = %.2f\n", reachable + Cmax * Davg);
}
else {
ans += (D - stationInfo[curPos].second ) / Davg * stationInfo[curPos].first;
printf("%.2f\n", ans);
}
//system("pause");
return 0;
}