Expedition (POJ2431)运用优先级队列解题

问题:Expedition(POJ2431)

你需要驾驶一辆卡车行驶L单位的距离。最开始时,卡车上有p单位的汽油。卡车每开一单位的距离需要消耗一单位的汽油。如果在途中车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点。在途中一共有n个加油站。第i个加油站在距离起点Ai单位距离的地方,最多可以给卡车加Bi单位的汽油。假设卡车的燃料箱的容量是无限大的。那么请问卡车是否能够到达终点?如果可以需要加多少次油?如果可以到达终点,输入最少加油次数,否则输出-1。

限制条件
1 N 10000
1 L 1000000 , 1 P 1000000
1 A i < L , 1 B i 100
输入样例:
N=4, L=25, P=10; //4个加油站,路程25,起始油量10
A={10,14,20,21}
B={10,5,2,4}
输出样例:
2(第一个和第二个加油站加油)
输入示例中的N比较小,但是在实际情况中N可以很大,当N很大时,一般的算法将花费大量时间,所以一个较好的算法是本题的解题关键。
对于本题我们可换一个思路。先不考虑加油问题,当汽车没油时,再从路过的加油站加油(因为路过时可以加油,我们在路过时不知道是否要在该站加油)。
那么在车没油时,我们可以已经路过了多个加油站,要选择哪个加油站加油呢?根据题目可知,我么的目的是为了求加油次数最少,所以我们要选择油量最多的加油站。
所以在这里就需要求出路过的加油站中油最多的加油站。因为只需要求出油最多的一个,所以不需要全排序,而且经过的加油站在不断增加,有因此我么选择堆排序是最好的选择。

有关堆排序的内容
https://blog.csdn.net/qq_28120673/article/details/81066756

算法设计如下:

  • 在经过加油站 A i 时,往优先级队列中加 B i
  • 当燃料耗尽时有两种选择
    • 如果优先队列也为空,则无法到达终点
    • 优先队列不为空,从队列中取出最大元素,并用来给加油站加油

代码如下:

#include <iostream>
#include <queue>

#define  MAX_N 10000
using namespace std;


int L, P ,N;
int A[MAX_N+1], B[MAX_N+1];

void init(){
    cin>>N>>L>>P;
    for(int i=0;i<N;i++){
       cin>>A[i];
    }
    for(int i=0;i<N;i++)
    cin>>B[i];
    A[N]=L; //为了计算方便,将终点也设为加油站
    B[N]=0;
}

int solve(){
    priority_queue<int> que;
    int ans=0;//加油次数
    int pos=0;//所在位置
    int tank=P;//剩余油量

    for(int i=0;i<N;i++){
        int d=A[i]-pos;
       while (d>tank){
           if(que.empty()) {
              ans=-1;
               return ans;
           }
           tank+=que.top();
           que.pop();
           ans++;
       }
       tank=tank-(A[i]-pos);
       pos=A[i];
       que.push(B[i]);
    }
    return ans;
}
int main(){
    init();
    cout<<solve();
}

猜你喜欢

转载自blog.csdn.net/qq_28120673/article/details/81076179
今日推荐