51nod 2636 卡车加油
题目链接:http://class.51nod.com/Challenge/Problem.html#problemId=2636
一、题目描述
一辆卡车,初始时距离终点L,油量为P,在起点到终点途中有n个加油站,每个加油站油量有限,而卡车的油箱容量无限,卡车在行车途中,每走一个单位的距离消耗一个单位的油量,给定n个加油站距离起点的距离A[i]以及油存储量B[i]。问卡车是否能到达终点,如果可达,最少需要加多少次油,否则输出-1。输入不保证有序。
1 <= n <= 10000; 1 <= L <= 1000000; 1 <= P <= 1000000;1≤A[i]<L,1≤B[i]≤100。
输入
第一行三个数L,P,n,以空格隔开,分别表示起点到终点的距离、现在的油量、中途加油站数; 之后n行,每行两个数A[i]和B[i],以空格隔开,表示该加油站到起点的距离和油存储量。
输出
输出一个数,表示最少的加油次数。
样例输入
100 15 2
15 75
90 25
样例输出
2
二、思路描述
在卡车开往终点的图中,只有在加油站才可以加油。
但是如果转换成“在到达加油站i时,就获得了一次在之后任何时候都可以加B[i]单位汽油的权利”,在解决问题上是一样的。
我们可以把每次到加油站的油量都存到优先队列里。
那么,想要加油的次数尽可能少,当燃料用完之后再去看加哪个B[i]应该是最优的,在燃料为0时,应该选油量B[i]最大的加油站。
由此可见,需要一直动态的维护一个最大油量,就应用到了优先队列的性质。
那么算法的步骤如下:
1、当经过加油站时,将B[i]加入优先队列中。
2、如果燃料为0
3、如果优先队列为空,则表示无油可加,无法到达终点
4、否则取出优先队列中最大的元素,用来给卡车加油
那么现在有个问题:如果我要到最大的供油加油站就得使用几个油箱中的油。可是我最后最大的供油加油站却可以供从起点开到终点的油。
我最后就输出1了,实际上还有一些数字没有算进去。这要怎么解决呢?
可以定义一个v数组,v[a]=b代表位置a处有一个油量为b的加油站,输入a,b的时候就做这个操作。
遍历路的时候,就判断这个i上面有没有加油站(无:v[i]=0),if ( v[i] != 0 ) q.push(v[i]) 这个应该在if(p==0)前面写
三、复习优先队列
四、代码
#include<queue> #include<cstdio> #include<iostream> using namespace std; priority_queue <long long> q; long long l, p, n, a, b, ans=0, v[1000005]; int main(){ cin >> l >> p >> n; for(long long i = 1;i <= n;i++){ cin >> a >> b; v[a] = b; } for(long long i = 1;i < l;i++){ p--; if(v[i]){ q.push(v[i]); } if(p == 0){//如果暂且选择的油箱空了 if(q.empty()){//如果没有可以用的油箱了 ans = -1;//不能满足题目要求,最后输出-1 break; } else{//还有可以选择的油箱 p = q.top();//从大往下取油箱 ans++;//选择的油箱数量+1 q.pop(); //最大的油箱已经选过了,后面不能数了,去掉这个数 } } } cout << ans << endl; return 0; }