Expedition (汽车加油) 优先队列

这是第一个博客,有一点小激动,话不多说,先上问题。
**

题目

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

(N>=1&&N<=10000;L,P>=1&&L,P<=10000;AI>=1&&Ai<L;Bi>=1&&Bi<=100)

思路

由于途中加油站个数N可以很多,直接解决十分麻烦,可以换一种思路,理解为经过加油站就获得了加油的权利(但不一定加油),题意要求找出加油最少次数,故在油箱空的情况下,应优先选择可供给油量最多的加油站,这里就需要用到优先队列。
优先队列:
priority_queue<int ,vector,less > q1;(降序排列)
priority_queue<int ,deque,greater > q2;(升序排列)
本题中需使用降序排列。

代码

输入变量:

cin>>N>>L>>P;
for (int i=0;i<N;i++) cin>>A[i];
for (int i=0;i<N;i++) cin>>B[i];

建立优先队列并定义其它变量:

priority_queue<int,vector<int>,less<int> >q;
int res(0)/*最小加油次数*/,now(0)/*现在位置*/,oil/*油箱剩余油量*/=P;

方便起见将终点也视为加油站其中油量为L,距终点离为0。

    A[N]=L;
	B[N]=0;
	N++; 

现在开始行车,利用for循环,这里为了方便需要定义一个表示下一段需要走的距离记为d

d=A[i]-now;

接下来判断油是否够用 ,在不够用的情况下需要从优先队列中加油然后更新现在位置与油箱油量,如果够用进行到下一位置并直接更新现在位置与油箱油量。
代码如下:

for (int i=0;i<N;i++) {
		int d=A[i]-now;
		if (oil<d) {
			if (q.empty()) {
				cout<<"-1"<<endl;
				return ;
			}
			oil+=q.top();
			q.pop();
			res++;
		}
		now=A[i];
		oil-=d;
		q.push(B[i]);
	}

完整代码:

在这里插入代码片#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int N,L,P,A[100],B[100];
void solve() {
	A[N]=L;
	B[N]=0;
	N++; 
	priority_queue<int,vector<int>,less<int> >q;
	int res(0)/*最小加油次数*/,now(0)/*现在位置*/,oil/*油箱剩余油量*/=P;
	for (int i=0;i<N;i++) {
		int d=A[i]-now;
		if (oil<d) {
			if (q.empty()) {
				cout<<"-1"<<endl;
				return ;
			}
			oil+=q.top();
			q.pop();
			res++;
		}
		now=A[i];
		oil-=d;
		q.push(B[i]);
	}
	cout<<res<<endl;
} 
int main() {
	cin>>N>>L>>P;
	for (int i=0;i<N;i++) cin>>A[i];
	for (int i=0;i<N;i++) cin>>B[i];
	solve();
	return 0;
}

运行结果:
在这里插入图片描述
结束。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值