【poj 2431】探险
2016-07-22 15:34
260 查看
原题网址http://poj.org/problem?id=2431
题目翻译:
【问题描述】
一群奶牛抢了一辆卡车决定前往树林里探险。但是由于他们的驾驶技术太糟,油箱在路上弄破了,所以他们每前进一个单位的路程就会漏掉一个单位的油。为了修好油箱,奶牛们必须前往最近的城市(不会超过1000000单位路程)。在当前位置和城市之间有N个加油站,奶牛可以在加油站加1到100单位的油。
对于人来说,树林是危险的地方,对奶牛来说,更是这样,所以奶牛门尽可能的少停站加油,幸运的是,这辆卡车的油箱非常大,你可以认为它的容量是无限大的。卡车在离城市P单位时还有L个单位的油。
你要计算出奶牛们至少要停几站才能到城市,或者奶牛们根本到不了城市。
【输入格式】
第一行一个整数N,接下来的N行,每行包含两个用空格隔开的整数,分别表示该加油站离城市的距离和最多可以加多少油。最后一行包含的两个整数为P和L。
【输出格式】
如果卡车能到达城市,输出最少要停的次数,否则输出-1。
【输入样例】
【输出样例】
【样例解释】
现在卡车离城市25个单位,卡车离有10个单位的油。在路上,有4个加油站,分别距离城市4,5,11,15,分别距离卡车则为21,20,14,10。这些加油站分别最多可加油4,2,5,10个单位。
开10个单位,加满10单位油,再开4个单位,加满5单位油,接着直接开到城市。
【数据范围】
题目大意:有一辆车,每走一个单位会消耗一个单位的油,路上有n个加油站,每个在P[i]位置的加油站可以加L[i]单位的油,要求从P开到0需要的最少加油次数。
算法:贪心;
因为车是从坐标P开向0,且每个加油站的坐标属于[0,P],所以先把加油站按坐标P从大到小排序(因为车先经过坐标更大的加油站)。
贪心策略:设车当前不加油能跑的极限位置是R,显然R=当前车的坐标P-邮箱内剩余油L;
在加油站中依次查找坐标值大于等于R的(车能不加油到达的加油站),显然必须在这些加油站中选一个加油站加油,那么选那个加油站呢?应该选能加更多油的加油站加油。
证明:分两种情况:
1.假设在能加最多油的加油站之前加油,则显然不如在能加最多油的加油站优。
2.假设在能加最多油的加油站之后加油,虽然说这一次车的起始位置更为靠前,但是在走到这个位置时会消耗更多的油,也不如最多油的加油站最优。
算法主框架:在汽车能到达的加油站中,查找能加最多油的加油站加油,下一次从这个加油站出发,继续寻找能到达的加油站加油,直到汽车已经能到城市(即R<=0),为止,每加一次,都统计一次次数。如果中途有存在找不到能到达的加油站的情况则说明无解。
查找过程用优先队列优化(注意这里每次加油后不用清空队列,虽然假设的是汽车用完了油,但也可以不用完,在先前油多的加油站多加油)
题目翻译:
【问题描述】
一群奶牛抢了一辆卡车决定前往树林里探险。但是由于他们的驾驶技术太糟,油箱在路上弄破了,所以他们每前进一个单位的路程就会漏掉一个单位的油。为了修好油箱,奶牛们必须前往最近的城市(不会超过1000000单位路程)。在当前位置和城市之间有N个加油站,奶牛可以在加油站加1到100单位的油。
对于人来说,树林是危险的地方,对奶牛来说,更是这样,所以奶牛门尽可能的少停站加油,幸运的是,这辆卡车的油箱非常大,你可以认为它的容量是无限大的。卡车在离城市P单位时还有L个单位的油。
你要计算出奶牛们至少要停几站才能到城市,或者奶牛们根本到不了城市。
【输入格式】
第一行一个整数N,接下来的N行,每行包含两个用空格隔开的整数,分别表示该加油站离城市的距离和最多可以加多少油。最后一行包含的两个整数为P和L。
【输出格式】
如果卡车能到达城市,输出最少要停的次数,否则输出-1。
【输入样例】
4 4 4 5 2 11 5 15 10 25 10
【输出样例】
2
【样例解释】
现在卡车离城市25个单位,卡车离有10个单位的油。在路上,有4个加油站,分别距离城市4,5,11,15,分别距离卡车则为21,20,14,10。这些加油站分别最多可加油4,2,5,10个单位。
开10个单位,加满10单位油,再开4个单位,加满5单位油,接着直接开到城市。
【数据范围】
0<N<=10 000 , 0<P<=1 000 000
题目大意:有一辆车,每走一个单位会消耗一个单位的油,路上有n个加油站,每个在P[i]位置的加油站可以加L[i]单位的油,要求从P开到0需要的最少加油次数。
算法:贪心;
因为车是从坐标P开向0,且每个加油站的坐标属于[0,P],所以先把加油站按坐标P从大到小排序(因为车先经过坐标更大的加油站)。
贪心策略:设车当前不加油能跑的极限位置是R,显然R=当前车的坐标P-邮箱内剩余油L;
在加油站中依次查找坐标值大于等于R的(车能不加油到达的加油站),显然必须在这些加油站中选一个加油站加油,那么选那个加油站呢?应该选能加更多油的加油站加油。
证明:分两种情况:
1.假设在能加最多油的加油站之前加油,则显然不如在能加最多油的加油站优。
2.假设在能加最多油的加油站之后加油,虽然说这一次车的起始位置更为靠前,但是在走到这个位置时会消耗更多的油,也不如最多油的加油站最优。
算法主框架:在汽车能到达的加油站中,查找能加最多油的加油站加油,下一次从这个加油站出发,继续寻找能到达的加油站加油,直到汽车已经能到城市(即R<=0),为止,每加一次,都统计一次次数。如果中途有存在找不到能到达的加油站的情况则说明无解。
查找过程用优先队列优化(注意这里每次加油后不用清空队列,虽然假设的是汽车用完了油,但也可以不用完,在先前油多的加油站多加油)
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #include<algorithm> #define maxn 10010 using namespace std; int n,P,L; bool vis[maxn];//标记已经在队列中的加油站 struct data { int p,l; }A[maxn]; struct cmpq { bool operator()(data a,data b) { return a.l<b.l; } }; bool cmp(data a,data b) { return a.p>b.p; } void solve() { sort(A+1,A+n+1,cmp); priority_queue<data,vector<data>,cmpq>pq; int R=P-L,ok=1,cnt=0; while(R>0 && ok) { for(int i=1;i<=n;i++)if(A[i].p>=R && !vis[i]) { pq.push(A[i]); vis[i]=1; } if(!pq.empty()) { data t=pq.top();pq.pop(); R=R-t.l;//下次汽车能到的极限位置是R-t.l cnt++; } else ok=0;//队列为空则说明没有加油站可以到达,无解 //while(!pq.empty())pq.pop(); } if(ok)printf("%d\n",cnt); else printf("-1\n"); } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&A[i].p,&A[i].l); } scanf("%d%d",&P,&L); solve(); }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解