优先队列

定义:能够完成下列操作的数据结构叫做优先队列。

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
",ans);
} 


原文地址:https://www.cnblogs.com/Tovi/p/6194819.html