Tsinsen A1122 旅行家的预算

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;
}

你可能感兴趣的:(ACM-01)