POJ 2431 Expedition(贪心+优先队列)
来源:互联网 发布:淘宝买家如何开店 编辑:程序博客网 时间:2024/05/01 09:43
原题地址
http://poj.org/problem?id=2431
题意:一辆有P单位汽油的卡车,刚开始停在距离起点处,距离终点L单位距离,卡车每开一单位距离就要消耗一单位汽油。在途中一共有N个加油站,每个加油站有各自的位置和油量。假设卡车的燃料箱容量无限,请问最少需要加几次油到达终点。如果不能到达则输出-1。
解题思路
这道题需要一个切入点,有了这个思想,贪心的做法写起来就很简单了。
在卡车开往终点的途中,只有在加油站可以加油,转换一下思路,每经过一个加油站 i,就获得了一次在之后的任何时候都可以加 i 的油的权利,也就是把 i 作为了储备的油,之后需要加油的时候,就认为是在之前经过的加油站里加油就可以了(无疑是加满)。
因为希望停的次数尽可能少,所以当燃料为0了之后再进行加油、且选经过的油站里油量最大的加,是很好的办法。每次贪心取最大,数据结构上最合适的就是最大堆形式的优先队列啦。
实现时,先对所有油站的距离排序(给出的是距离终点的距离,先转换为距离起点的距离),每经过一个油站就把该油站的油量加入优先队列,当没油时,如果优先队列已经空了,说明之前的油都加完了,否则取出最大数值加油。
编码了两种实现,都可以AC:
- 《挑战程序设计竞赛》书上给出的代码solve_book(),它以每次能否到达下一个加油站为判断标准(其实不是很懂?和它描述的思路不那么对应)。有个处理技巧,将终点也作为一个空的加油站,做循环的时候就不用再处理边界条件。
- 自己按照思路实现的代码solve_mine()。每次把油耗尽之后再回头看是否还有油可以加,而不是判断能否到达下一个加油站。
AC代码
#include <iostream>#include <cstdio>#include <algorithm>#include <queue>using namespace std;const int maxn = 10005;typedef struct node{ int dist, fuel; bool operator < (const node A) const //距离升序 { return this->dist < A.dist; }}NODE;int n, length, left_fuel;NODE stop[maxn];void solve_book() //书上代码:以能否到达下一个加油站为判断条件{ int pos = 0, pass = 0; //把终点也当作一个空油站 stop[n].dist = length; stop[n].fuel = 0; n++; sort(stop, stop+n); //按距离排序 priority_queue<int> pq; for(int i = 0; i<n; ++i) { int between = stop[i].dist - pos; //距离下一个加油站 while (left_fuel < between) //到不了新的加油站 { if (pq.empty()) //队列已空,没储备油可加 { cout << -1 << endl; return; } left_fuel += pq.top(); pq.pop(); ++pass; //加油次数+1 } //到达新的加油站 pos = stop[i].dist; left_fuel -= between; pq.push(stop[i].fuel); //加入储备油站 } cout << pass << endl;}void solve_mine() //自己实现:每次开到最远,再回头看油{ sort(stop, stop+n); //按距离排序 priority_queue<int> pq; int pos = 0, index = 0, ans = 0; //index-1指向开过的最右边站点 while(1) { pos += left_fuel; //当前油量开到的最远点 if (pos >= length) //能开过终点 { cout << ans << endl; return; } while (stop[index].dist <= pos) //统计此次开过的站 { pq.push(stop[index].fuel); index++; } if (pq.empty()) //无油可加 { cout << -1 << endl; return; } //加队列里的最大油量 left_fuel = pq.top(); pq.pop(); ans++; }}int main(){ //freopen("C:/Users/DELL/Desktop/a.txt", "r", stdin); ios::sync_with_stdio(false); cin >> n; for (int i = 0; i<n; ++i) cin >> stop[i].dist >> stop[i].fuel; cin >> length >> left_fuel; for (int i = 0; i<n; ++i) //转换为到起点的距离 stop[i].dist = length - stop[i].dist; //solve(); solve_mine(); return 0;}
算法复杂度:O(n)
耗时:141ms
0 0
- POJ 2431 Expedition (优先队列+贪心)
- POJ 2431 Expedition (贪心 + 优先队列)
- poj 2431 Expedition (贪心+优先队列)
- POJ 2431 Expedition (贪心、优先队列)
- poj 2431Expedition(优先队列+贪心)
- POJ 2431 Expedition (贪心、优先队列)
- POJ 2431 Expedition (贪心+优先队列)
- POJ 2431 Expedition(贪心+优先队列)
- POJ 2431 Expedition (贪心 + 优先队列)
- POJ 2431 Expedition (优先队列 + 贪心)
- POJ 2431 Expedition(贪心+优先队列)
- poj 2431 Expedition(优先队列+贪心)
- poj 2431 Expedition 贪心 + 优先队列
- poj 2431 Expedition 贪心 + 优先队列
- 2431Expedition POJ- 优先队列 + 贪心
- POJ 2431 Expedition (贪心+优先队列)
- poj 2431 Expedition 贪心 + 优先队列
- poj,2431Expedition 贪心 + 优先队列
- Codeforces798D Mike and distribution
- HDU 1159 Common Subsequence【LCS(dp)】
- restTemplate公用魔板使用及中文乱码问题
- 中序遍历树(不一定是二叉树)
- SMTP邮件传输协议发送邮件和附件
- POJ 2431 Expedition(贪心+优先队列)
- linux基础3.12shell脚本2
- NIO中通道(Channel)
- 【Summary】——>Web组.Week4
- Struts2框架的基本使用(三)
- Nginx隐藏响应头信息的Server信息和版本信息
- JMeter学习笔记10-Graph Results介绍
- 轮转调度算法(C语言描述)
- 第六讲、软件包管理