优先队列的使用——Expedition
Posted lfri
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优先队列的使用——Expedition相关的知识,希望对你有一定的参考价值。
一、题目描述
你需要驾驶一辆卡车行驶L单位距离。最开始时,卡车上有P单位的汽油。卡车每开1单位距离需要消耗1单位的汽油。如果在途中车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点。中途共有N个加油站,第i个加油站距离终点Ai单位距离,最多可以给卡车加Bi单位汽油。假设卡车的燃料箱的容量是无限大的,无论加多少油都没有问题。那么请问卡车是否能到达终点?如果可以,最少需要加多少次油?如果不可以输出-1。(1 ≤ N ≤ 10000,1 ≤ L ≤ 1000000,1 ≤ P ≤ 1000000,1 ≤ Ai ≤ L,1 ≤ Bi ≤ 100)
二、问题分析
由于加油站的数量非常大,必须像一个高效的解法。
在卡车开往终点的途中,只有在加油站才可以加油。我们换一种思考方式,如果认为“在到达加油站时i时,再次之后的任何时候都获得了加Bi油的权利”。因为希望到达终点的加油次数尽可能地少,我们可以加经过地加油站的加油量放入优先队列,当油量不足以到达下一站,则取出优先队列中的最大值,其实就是贪心算法,取所有权力中的最大值,最坏的情况时,每次油量都不够,需要从队列中取,此时时间复杂度O(nlogn).
三、代码实现
1 #include<stdio.h> 2 #include<iostream> 3 #include<queue> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 8 const int maxn = 10000 + 10; 9 struct Station 10 { 11 int pos; 12 int fuel; 13 bool operator < (const Station &n)const { 14 return (pos < n.pos); 15 } 16 }sta[maxn]; 17 int n, L, P; 18 19 void slove() 20 { 21 //把终点也认为是一个加油站,写起来更加方便 22 sta[n].pos = L; 23 sta[n].fuel= 0; 24 n++; 25 26 priority_queue<int>que; 27 int ans = 0,pos = 0, tank = P; //pos表示当前位置,tank表示当前油量 28 29 sort(sta, sta + n); //使各加油站的位置从小到大排列 30 31 for (int i = 0; i < n; i++) 32 { 33 int d = sta[i].pos - pos; 34 35 //油量不够则加油 36 while (tank - d < 0) 37 { 38 if (que.empty()) 39 { 40 printf("-1 "); 41 return; 42 } 43 tank += que.top(); 44 que.pop(); 45 ans++; 46 } 47 tank -= d; 48 pos = sta[i].pos; 49 que.push(sta[i].fuel); 50 } 51 printf("%d ", ans); 52 } 53 int main() 54 { 55 scanf("%d", &n); 56 for (int i = 0; i < n; i++) 57 scanf("%d%d", &sta[i].pos, &sta[i].fuel); 58 scanf("%d%d", &L, &P); 59 for (int i = 0; i < n; i++) 60 sta[i].pos = L - sta[i].pos; 61 62 slove(); 63 return 0; 64 }
四、总结
熟练应用优先队列能很好的解决许多问题。
以上是关于优先队列的使用——Expedition的主要内容,如果未能解决你的问题,请参考以下文章