1033 To Fill or Not to Fill (25 分)
题目分析
我跟这道题交手已经不下4次了,终于把它给AC了。这是一道贪心的问题,贪心的策略也比较好想,那就是保证油的单价一定是最便宜的。但是这其中有一些细节,如果不仔细很容易出错。
解题思路
我们在每个站点考虑要加的油量,参照的标准是当前站点的油价和后续站点的油价。可能面临的情况有如下几种:
下一个站点能够到达
这时有两种情况:
- 下一个站点的油价小于或等于当前站点
此时的策略很简单,即保证油恰好够跑到下一个站点,如果此时油箱中的油量大于所需值,就不加。 - 下一个站点的油价大于当前站点
如果在我们能够到达的最大距离内有油价小于我们的站点,那么就让油量保持到恰好够跑到这个站点;如果在我们能够到达的最大距离内没有油价小于我们的站点,那么就在当前站点把油箱加满。
根据上述的分析我们需要一个参数c
来记录当前油箱中的油量,在每次加油之后都要更新他的值。上述的策略能够保证是最优的策略,具体的证明略。
下一个站点不能到达
这就是说两个站点之间的距离超过了满油能够跑的最大距离,那么显然我们无法到达目的地,此时输出能够到达的最大距离,也就是当前站点距离起点的距离加上满油能够跑的最大距离。
最后还要注意的是可能第一个站点距离出发地的距离大于0,那么这个时候能够行驶的最大距离就是0.
AC代码
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node {
double p;
double dis; // 从当前站点到下一个站点的距离
};
bool cmp(node a, node b) {
return a.dis < b.dis;
}
vector<node> v;
double c_max, D, D_avg, d_max;
int n;
int main() {
scanf("%lf %lf %lf %d", &c_max, &D, &D_avg, &n);
d_max = c_max * D_avg;
v.resize(n + 1);
for (int i = 0; i < n; ++i) {
double a, b;
scanf("%lf %lf", &a, &b);
v[i].p = a;
v[i].dis = b;
}
sort(v.begin(), v.end() - 1, cmp);
if (v[0].dis != 0) {
printf("The maximum travel distance = 0.00\n");
return 0;
}
for (int i = 0; i < n - 1; ++i) {
v[i].dis = v[i + 1].dis - v[i].dis;
}
v[n - 1].dis = D - v[n - 1].dis;
v[n].dis = 0, v[n].p = 0;
int i = 0;
double cost = 0, c = 0;
while(i <= n) {
if (v[i].dis <= d_max) { // 下一个站点能够到达
if (v[i].p >= v[i + 1].p) { // 下一个站点的油价小于或等于当前站点
if (v[i].dis / D_avg - c < 0) {
c -= v[i].dis / D_avg;
} else {
cost += (v[i].dis / D_avg - c) * v[i].p;
c = 0;
}
i++;
} else {
int temp = i;
double sumd = v[i].dis;
i++;
while(sumd <= d_max && v[temp].p < v[i].p) {
sumd += v[i].dis;
i++;
}
if (sumd > d_max) { // 如果在能够到达的最大距离内没有油价更小的站点
i--; // 这一句很容易漏掉,如果不仔细考虑的话
sumd -= v[i].dis;
cost += (c_max - c) * v[temp].p;
c = c_max - sumd / D_avg;
} else {
if (sumd / D_avg - c < 0) {
c -= sumd / D_avg;
} else {
cost += (sumd / D_avg - c) * v[temp].p;
c = 0;
}
}
}
}
else {
double d1 = 0;
for (int j = 0; j < i; ++j) {
d1 += v[j].dis;
}
printf("The maximum travel distance = %.2f\n", d1 + d_max);
return 0;
}
}
printf("%.2f\n", cost);
return 0;
}