加油站
题目描述
奶牛们开车到郊外旅游,由于驾驶技术不行,不小心撞到了石头,油箱漏油了。现在汽车每走一单位距离,油箱就损耗和漏掉共一单位油。
为了修车,必须把车开到最近的小镇(不会超过10,000,000单位距离),到小镇的路可以认为是在一条直线上。从现在的位置到小镇途中, 共有 N (1 <= N<=50,000) 个加油点,第i个加油点位于距离小镇有D_i (1 <= D_i< L)单位距离的地方,该加油站储油F_i (1 <= F_i<= 100)单位.由于路途艰险,奶牛们想尽量把加油的次数减到最少.汽车的油箱可以认为是无穷大. 汽车现在为于距离小镇L个单位距离的地方,并且有P单位的油(1 <= P <=10,000,000).请你计算最少要加多少次油才能到达小镇,或者汽车根本开不到小镇. 注意:在同一地点,可能有多个加油站,但是,在计算时,它们是独立的,认为是两个不同的加油站。
输入格式 1854.in
* 第1行: 三个整数: N、 L、P.
* 第 2..N+1行: 两个整数: D_i 、 F_i. 对应着一个加油站。
输出格式 1854.out
* 一行: 到达小镇需要的最少的加油次数,如果无法到达小镇, 输出-1.
输入样例 1854.in
4 25 10
4 4
5 2
11 5
15 10
输出样例 1854.out
2
【输入解释】
汽车现在在距离小镇25个单位距离的地方,汽车有10个单位的汽油.
在途中, 有 4 个加油站,他们分别位于距离小镇: 4、 5、 11、15个单位距离的地方。(可以看出,它们跟汽车现在位置的距离分别是:21、20、14、10)。这4个加油站的储油量分别是: 4、 2、 5、10。
【输出解释】
汽车开10单位距离后, 停车加10单位的油, 再开4单位距离,停车加5单位的油, 然后就可以开到小镇了。
这题用到了贪心+优先队列。
思路分析:
当车遇到加油站的时候,就直接加油,一定好吗?答案是否定的,当开到某一个加油站的时候,花一次加油的机会,加到的油还不一定多,而后面同样能到达的加油站,说不定能加更多的油。
因此贪心的策略就是,尽量走到能走的地方,取一个加油量最大的加油。
具体实现:
当走到某段路的时候,便看看从now能不能走到这个位置(油量够不够)
如果不够,就要加油,可是如果在之间的这一段路都没有一个加油站,那么优先队列q会为空,无解。
否则就在加油最多的地方加油,也就是优先队列的top,把这些油加进来以后,再把这个加油站删掉。
进行上述重复操作,直到油量,可以到达此时的地方。
#include
#include
#include
#include
using namespace std;
const int maxn=50005;
int n,l,p,b,ans=0,f;
priority_queue
q; struct you { int far,va; }a[maxn]; bool cmp(you x,you y) { if(x.far==y.far) return x.va>y.va; return x.far
>n>>l>>p; for(int i=1;i<=n;i++) { cin>>b>>f; a[i].far=l-b; a[i].va=f; } sort(a+1,a+1+n,cmp); int head=1,tail=0,now=0,v=0;//now为现在在哪 a[n+1].far=l; for(int i=1;i<=n+1;i++) { while(a[i].far-now>p)//p为油 { if(q.empty()) { v=1; break; } p+=q.top(); q.pop(); ans++; } if(v==1) break; p-=(a[i].far-now); now=a[i].far; q.push(a[i].va);//注意这里不要存错参数啦!!! } if(v==1) cout<<-1<