【题解】旅行家的预算(贪心)

八中OJ

洛谷

这题太复杂了,能否全A看数据。。。

很好的一道模拟贪心题

算法原理(优先级)如下:

1.枚举途中经过的加油站,每经过一个加油站,计算一次花费

2.在一个加油站所需要加的油,就是能够支持它到达下一个油价比它低的加油站的量;

3.如果在这个加油站即使加满油,都不能到达一个比它油价低的加油站,(1)就把油箱加满,前往能够到达的加油站中油价最低的那个;(2)或者直接到终点;

4.如果在这个加油站即使加满油,都不能到达任意一个加油站,也不能到达终点城市,说明无解;

  • 先考虑2再考虑3,2一定划算,且无后续性

  • 第二点:注意不仅要省钱,还要是最近的加油站(尽早省钱美滋滋)

  • 第三点:前提是不省钱,注意要考虑直接到终点的情形

  • 第三点:为什么要加满油?因为这样可以减少在下一个加油站(价格更贵)所需要加的油量。

贪心思路就是这样,能否实现看本事

first try : 60

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; double d1,c,d2,n,p1,lc,ans; struct liu{ double d,p,h; }a[105]; int main() { scanf("%lf%lf%lf%lf%lf",&d1,&c,&d2,&p1,&n); lc=c*d2; for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].h,&a[i].d,&a[i].p); double i=0,yq=p1; while(i<d1) { double t=i+lc,_min=1e9; int bh=0; for(int j=1;j<=n;j++) { if(a[j].d>i&&a[j].d<=t&&a[j].p<_min&&a[j].d<d1) _min=a[j].p,bh=j; } if(bh==0) { if(t>=d1) { ans+=(d1-i)*yq/d2; break; } else { printf("No solution"); return 0; } } else { if(t>=d1) { if(yq<=_min) { ans+=(d1-i)*yq/d2; break; } } ans+=(a[bh].d-i)*yq/d2,i=a[bh].d,yq=a[bh].p; } } printf("%.2lf",ans); } }

错因:

1.未考虑是否省钱

2.不是选的最近的油站,而是选最便宜的

3.未考虑剩余油

样例输入: 475.6 11.9 27.4 14.98 6 102.0 9.99 220.0 13.29 256.3 14.79 275.0 10.29 277.6 11.29 381.8 10.09 样例输出: 192.15 真实输出: 192.32

于是我权衡了网上思路,进行第二次尝试

正解:

second try : 100

#include<cstdio> #include<algorithm> #include<cstring> using namespace std; double d1,c,d2,n,p1,lc,ans,yx; struct liu{ double d,p; }a[10005]; int main() { scanf("%lf%lf%lf%lf%lf",&d1,&c,&d2,&p1,&n); lc=c*d2; for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].d,&a[i].p); double i=0,yq=p1; while(i<d1) { double t=i+lc,_min=1e9; int bh=0; for(int j=1;j<=n;j++) {//在范围内寻找能省钱且最近的 if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<yq&&a[j].d<_min) { bh=j,_min=a[j].d; } } if(bh!=0) ans+=((a[bh].d-i)*yq-yx)/d2,i=a[bh].d,yq=a[bh].p,yx=0; //剩余油不可能直接使到达 //不能找到,分为能否直接到达终点以及有无后续加油站两方面同时考虑 else { _min=1e9,bh=0; for(int j=1;j<=n;j++) {//在范围内寻找最便宜(并不省钱)的加油站 if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<_min) _min=a[j].p,bh=j; } //无后续加油站且无法直接到达终点 if(bh==0&&t<d1) { printf("No Solution"); return 0; } //能直接到达,最划算 if(t>=d1) { if(yx<(d1-i)/d2) { ans+=((d1-i)/d2-yx)*yq; } break; } //不能直接到达但有后续加油站,先加满(省钱),记录剩余油的多少 //加满和到最便宜的地方是关键 else { ans+=(c-yx)*yq; yx=c-(a[bh].d-i)/d2; yq=a[bh].p,i=a[bh].d; } } } printf("%.2lf",ans); }

写得算完整了,欢迎打脸质疑我

仔细品味两次找油站!第一次是省钱且最近,第二次只是最便宜

(完)


__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530441.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(28)  评论(0编辑  收藏  举报  
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示