Noip 1999 / P1016 旅行家的预算

这是一篇关于如何使用贪心算法和模拟解决旅行家在有限预算下从一个城市到另一个城市的最少费用问题的博客。文章指出,首先在起点必须加油,并探讨了如何确定加油量以达到最低费用。在某些情况下,需要判断是否能到达下一个加油站,如果不能则输出"No Solution"。此外,博主还提到在油价最便宜的加油站加油可以减少费用,但关键在于在价格下降的区间内不需要直达最便宜的站,而是遇到更便宜的就加油。文章通过示例解释了这一策略,并指出原有代码存在的问题,改进后得到了正确的解决方案。

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

这是一道贪心 + 模拟的题。

贪心思路比较好想,很考验模拟功底。难点在于需要维护的东西很多。


题目在这里

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市,途中有N个加油站,有选择性地加油。若能到达目的地,输出最少费用;反之,输出“No Solution”。

样例输入
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2

样例输出
26.95

我们可以定义一个结构体来储存,第i个加油站与起点的距离,和每升油的价钱(不定义也没事,也就用2或3个数组而已)

const int size = 505;
struct T {
   
    int index; 
    double p, f;
} a[size];

首先,因为最开始油箱是空的(题目给出了的),所以在起点必须加油,然后我们需要思考的是加多少油,也就是思考这道题的贪心策略————怎么加油使得费用最少。

我们还要思考的是什么时候输出“No Solution”。举个例子:

input:10 2 1 5 2
       5 10
       6 7

分析一下数据:油箱最大容量是2升,每升最多行驶距离为1,所以我们可以算出一次加油后最多能行驶的距离为2。

而第一个加油站与起点的距离为5,即使在起点加满油也无法到达第一个加油站,所以旅行失败,输出”No Solution“。

之后也是同理,设加满油能行驶的最大距离为 M a x Max Max,只要 a [ i ] . f − a [ i − 1 ] . f > M a x a[i].f - a[i - 1].f > Max a[i].fa[i1].f>Max的都是无解的。

可以在输入时预处理,筛出失败的,如下

 a[0].f = 0;
 for (int i = 1; i <= N; i++) {
   
        scanf("%lf %lf", &a[i].f, &a[i].p);
        if (a[i].f - a[i - 1].f > C * D) {
   	//C * D为加满油行驶的最大距离
            printf("No Solution");
            return 0;
        }
    }

要想费用最少,不难想到在油价最便宜的加油站加油。但仅仅这样范围太大了,但我们由上一种情况可知,可选的加油站距离起点的距离肯定在a[i].f ~ a[i].f + C * D之间。

这里又需要分两种情况:1.在区间内有油价低于当前油价的加油站;2.没有油价低于当前油价的加油站。

若有,且剩余油量无法到达该加油站,则在当前加油站加油,加到恰好能到达该加油站的油量即可;否则,就直接去到该加油站。

若没有,则在当前加油站加满油,开到此区间中油价最便宜的加油站再做这样的考虑。最重要的一点是,在这种情况中还要判断,如果当前加油站与目的地距离小于等于C * D,就可

加油至刚好到目的地的油量。

题目中还提示了你可能还会有N为0的毒瘤存在,因此我试了试,我这个想法在N为0时可能没有输出,所以要特判一下。

在我的程序里,需要维护的东西有4个:1.费用(必须的啊);2.所处加油站的编号;3.已经行驶的距离;4.剩下的油量。

于是我便开始了我的的尝试:

#include <cstdio>
#include <climits>
#include <algorithm>
using namespace std;
const int size = 505;
struct T {
   
    double p, f;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值