优先队列
定义:能够完成下列操作的数据结构叫做优先队列。
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); }