http://oj.tsinsen.com/ViewGProblem.page?gpid=A1122
分析:浮点精度和一些边界条件弄得我心惊胆战的。这个题从算法来说不难,先读入输入,按顺序一个一个经过站点(将起点标记为0, 终点标记为n+1),成功经过站点则将其加入【待选加油序列】——这里根据的是经过某一站点,在当时加油和以后判断需要加油时“穿越”回去加油在逻辑上是等价的。加油序列按照油价排序,每次都加至刚好能到下一节点,并注意保存在某油站加过的油量——因为一旦这个值超过油箱容量,则不能再在这个站点加油。其他一些细节,比如判断“No Solution”之类的,看看代码就可以了。
代码:
#include "cstdio"
#include "vector"
#include "algorithm"
using namespace std;
struct Node { double d, p, c; }s[10050];
bool f(const Node & a, const Node & b) { return a.d < b.d; }
bool h(const Node & a, const Node & b) { return a.p > b.p; }
vector < Node > q;
int main() {
bool Can = true;
double d1, c, d2, cost = 0;
int n;
scanf("%lf%lf%lf%lf%d", &d1, &c, &d2, &s[0].p, &n);
s[0].d = 0;
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", &s[i].d, &s[i].p);
s[n + 1].d = d1; s[n + 1].p = 0;
sort(s, s + n + 2, f);
for (int i = 0; i <= n + 1; ++i)
s[i].c = 0;
q.push_back(s[0]);
for (int i = 1; i <= n + 1; ++i) {
double dist = s[i].d - s[i - 1].d;
double need = dist / d2;
if (need > c) { Can = false; break; }
while (need > 0) {
if (q[q.size() - 1].c > c) q.pop_back();
if (need - (c - q[q.size() - 1].c) < 0) {
cost += need * q[q.size() - 1].p;
q[q.size() - 1].c += need;
break;
}
else {
cost += (c - q[q.size() - 1].c) * q[q.size() - 1].p;
need -= (c - q[q.size() - 1].c); q.pop_back();
}
}
q.push_back(s[i]); sort(q.begin(), q.end(), h);
}
if (Can) printf("%.2lf\n", cost);
else puts("No Solution");
return 0;
}