CNUOJ 0576 加油

时间:2021-08-06 05:32:40

40017074加油

难度级别:C; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

你需要驾驶一辆汽车行驶S个单位的距离。最开始汽车上有P个单位的汽油,汽车每开行1个单位的距离需要消耗1个单位的汽油。如果汽车中途汽油耗尽,将无法继续行驶,因此也就无法到达终点。途中一共有N个加油站,第i个加油站距离起点的距离为Ai个单位距离,第i个加油站你最多可以给汽车加Bi个单位的汽油。假设汽车的邮箱无限大,根据所给的数据,请你计算汽车能否达到终点,如果能到达终点,输出最少需要加油的次数,如果不能到达终点,输出-1。

输入
第一行共三个正整数,分别表示N、S和P;第二行有N个正整数分别表示A1,A2,……,An;第三行有N个正整数分别表示B1,B2,……,Bn;每一行的各个数据两两之间用一个空格分隔。
输出
按要求输出结果。
输入示例
4 25 10
10 14 20 21
10 5 2 4
输出示例
2
其他说明
数据范围:0<N<=10000,0<S,P<=1000000,0<Ai<=S,0<Bi<=100.

咋一看这题就知道是小贪心了吧?

在汽车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站时,就获得了一次在之后的任何时候都可以加Bi单位汽油的权利”,在解决问题上应该也是一样的,而在之后需要加油时,就认为是在之前经过的加油站加的油就可以了。

那么,因为希望到达终点的加油次数少,所以我们把汽车剩余燃料耗到0时再加油看起来是不错的方法。在燃料为0时,找汽车从该阶段起点出发时到燃料为0时的位置内能加油最多的加油站,这是显然的。所以我们可以用队列(prioeity_queue)

在经过加油站i时,往优先队列里加入Bi(也就是说油还够,可以继续行驶)

途中燃料耗尽时,

♢如果优先队列也是空的,说明途中没有加油站,则无法达到终点,输出-1

♢否则取出优先队列最大值,并给汽车加油

注意,priority_queue队列中的top()是取目前队列中的最大值。

切莫忘记将输入数据按加油站从起点到终点的位置顺序(a[i])排序,输因为入时加油站不一定是按位置顺序输入的,我当时就在这磕着了......

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int ans,pos,n,s,p,i;//ans加油次数,pos现在位置
struct GasStation
{
int pos,gas;
GasStation(){
pos=0;
gas=0;
}
bool operator < (const GasStation b)const
{
return pos<b.pos;
}
}a[10001];
int main()
{
priority_queue<int> que;
scanf("%d%d%d",&n,&s,&p);
for(i=0;i<n;i++) scanf("%d",&a[i].pos);
for(i=0;i<n;i++) scanf("%d",&a[i].gas);
sort(a,a+n);
a[n].pos=s,a[n].gas=0,n++;
int tank=p;//油箱中汽油量
for(i=0;i<n;i++){
int d=a[i].pos-pos;//下一个加油站距离现在位置的距离
while(tank-d<0)//不断加油直到油量足够行驶到下一个加油站
{
if(que.empty()){
putchar('-'),putchar('1');
return 0;
}
tank+=que.top();
que.pop();
ans++;
}
tank-=d;
pos=a[i].pos;
que.push(a[i].gas);
}
printf("%d",ans);
return 0;
}

此题解来源于挑战程序设计竞赛(第2版)2.4节Expedition

原题来源于POJ2431