定义:能够完成下列操作的数据结构叫做优先队列。
1、插入一个数值
2、取出最小的数值(获得数值,并且删除)
优先队列示意图
/*Poj 2431
*题目大意:你需要驾驶一辆卡车行驶L单位距离。最开始时,卡车上有P单位的汽油。卡车没开1单位距离需要消耗1单位的汽油。
* 如果在途中车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点。在途中一共有N个加油站。第i个加油站站在距离
* 起点Ai单位距离的地方,最多可以给卡车加Bi单位汽油。假设卡车的燃料箱的容量是无限大的,无论加多少油都没有问题。
* 那么请问卡车是否能到达终点?如果可以,最少需要加多少次油?如果可以到达终点输出最少的加油次数,否则输出-1
*算法分析: 由于加油站的数量N非常大,必须想一个高效的解法。我们稍微变换一下思考方式。在卡车开往终点的途中,只有在加油站
* 才可以加油。但是,如果认为“在到达加油站i时,就获得了一次在之后的任何时候都可以加Bi单位汽油的权利”,在解决问题上
* 应该也是一样的。而在之后需要加油时,就认为是在之前经过的加油站加的油就可以了。那么,因为希望到达终点时加油次数尽可能少,
* 所以当燃料为0了之后再进行加油看上去是一个不错的方法。在燃料为0时,应该使用哪个加油站来加油呢?显然,应该选能加油量Bi最大的
* 加油站
* 为了高效的进行上述操作,我们可以使用从大到小的顺序依次取出数值的优先队列。
* 1、在经过加油站i时,往优先队列里面加入Bi。
* 2、当燃料空了时, a,如果优先队列也是空的,则无法到达终点
* b,否则取出优先队列中的最大元素,并用来给卡车加油。
*/
int L, P, N;
int A[MAX_N+1], B[MAX_N+1];
void solve() {
//为了写起来方便,我们把终点也认为是加油站
A[N] = L;
B[N] = 0;
N ++ ;
//维护加油站的优先队列
priority_queue<int> que;
//ans: 加油次数, pos:现在所在位置, tank:邮箱中汽油的量
int ans = 0, pos = 0, tank = P;
for (int i = 0; i<N; i++) {
//接下去要前进的距离
int d = A[i] - pos;
//不断加油直到油量足够行驶到下一个加油站
while (tank - d < 0) {
if (que.empty()) {
puts("-1");
return ;
}
tank += que.top();
que.pop();
ans ++ ;
}
tank -= d;
pos = A[i];
que.push(B[i]);
}
printf("%d\n",ans);
}