PAT 甲级 1033 To Fill or Not to Fill (25 分) 加油站问题-贪心

解决一个人从0位置到D位置的驾车问题,初始无油,途经不同油价的加油站。探讨如何以最小花费到达目的地,或者输出最远可达距离。采用贪心策略,当当前加油站加满油后可抵达的下一个加油站油价更高且未达终点时,应在当前站加满油。重复此过程,直至无法继续前进,输出最远可达位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

一个人要从0位置开车到D位置,开始车里没有油,路上有一些加油站可以任意加油,但是油有不同的价格

问能不能到达D位置,能到达的话输出最小花费,不能到达输出最远到达距离

思路:

从开始位置加油,往后走,但是加多少油我们不确定,因为假如后面有一个加油站的油便宜,那我们到这个加油站加油,走后面的路程就会花费更小,前提是我们能到这样的加油站;

如果当前加油站加满能到达的后面的加油站油价都大于当前加油站,而我们又没到达终点,这时候只能从当前加油站把油加满;然后从能到达的加油站里面,油价最低的那个加油站把油箱补满。

然后再往后寻找合适的加油站,重复上述两个步骤;如果当前加油站加满油后到达不了下一个加油站,那么就无解,输出最远到达位置

 

 

#include<bits/stdc++.h>
#define FI first
#define SE second
using namespace std;
typedef pair<double,int> P;
const int maxn = 1000 + 7;
const double INF = 2e9 + 7;;

int c, d, m, n;
struct node {
    int pos;
    double p;
}a[maxn];
bool cmp(node a, node b) {
    return a.pos < b.pos;
}
map<int,int> id;
void solve() {
    sort(a+1,a+1+n, cmp);
    for(int i = 1; i <= n+1; ++i) {
        id[a[i].pos] = i;
    }
    if(a[1].pos != 0) {
        printf("The maximum travel distance = 0.00\n");
        return;
    }
    int lpos = 0;
    double lp = a[1].p;
    double mod = 0;
    double ans = 0;
    for(int i = 1; i <= n+1; i = id[lpos]) {
        //cout << lp << " + " << lpos << " + " << ans << endl;
        if(lpos >= d) {
            printf("%.2f\n", ans);
            return;
        }
        double minp = INF; int minpos = -1;
        double nxp = INF, nxpos = -1;
        bool ok = true;
        for(int j = i+1; j <= n+1; ++j) {
            if((a[j].pos-lpos) > c*m) break;
            if(ok && (a[j].p < lp)) {
                nxp = a[j].p;
                nxpos = a[j].pos;
                ok = false;
            }
            if(a[j].p < minp) {
                minp = a[j].p;
                minpos = a[j].pos;
            }
        }
        if(minpos == -1) {
            lpos += c*m;
            printf("The maximum travel distance = %.2f", (double)lpos);
            return;
        }
        if(!ok) {
            minp = nxp;
            minpos = nxpos;
        }
        if(minp < lp) {
            ans += (lp * ((minpos-lpos) / (1.0*m) - mod));
            mod = 0;
            lp = minp;
            lpos = minpos;
        }
        else {
            ans += (lp * (c - mod));
            mod = (1.0*c - (minpos-lpos) / (1.0*m));
            lp = minp;
            lpos = minpos;
        }
    }

}
int main() {
    scanf("%d%d%d%d", &c, &d, &m, &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%lf%d", &a[i].p, &a[i].pos);
    }
    a[n+1].pos = d;
    a[n+1].p = 0;
    solve();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值