贪心算法例题(五)
最优加油方法
题目描述:
已知一条公路上,有一个起点与一个终点,这之间有n个加油站;已知从这n个加油站到终点的距离d与各个加油站可以加油的量 l,起点位置至终点的距离L与起始时刻油箱中汽油量P;假设使用1个单位的汽油即走一个单位的距离,油箱没有上线,最少加几次油,可以从起点开至终点?(如果无法到达,返回-1)
思考:
汽车经过n个加油站,对于这n个加油站,应该在哪个加油站停下来加油,最终既能到达终点,又使加油次数最少?
若按顺序遍历加油站,则面临:
如果在某个加油站停下来加油,可能是没有必要的,有可能不进行这次加油也能到达终点;
如果在某个加油站不停下来加油,可能由于汽油不够而无法到达终点或者后面要更多次的加油才能到达终点
贪心:
在油用光的时候加油最合适!
在油量最多的加油站加油最合适!
算法思路:
1、设置一个最大堆,用来存储经过加油站的汽油量
2、按照从起点至终点的方向,遍历各个加油站之间的距离
3、每次需要走两个加油站之间的距离d,如果发现汽油不够走距离d时,从最大堆中取出一个油量添加,直到可以足够走距离d
4、如果把最大堆的汽油都添加仍然不够进行距离d,则无法达到终点
5、当前油量p减少d
6、将当前加油站油量添加至最大堆
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
bool comp(const pair<int, int>& p, const pair<int, int>& p1)
{
return p.first > p1.first;
}
int function(int L,int P,vector<pair<int, int> >& stop)
{
priority_queue<int> Q;
int result = 0;
stop.push_back(make_pair(0, 0));
sort(stop.begin(), stop.end(), comp);
for (int i = 0;i < stop.size();i++)
{
int dis = L - stop[i].first;
while (!Q.empty()&&P<dis)
{
P += Q.top();
Q.pop();
result++;
}
if (Q.empty() && P < dis)
{
return -1;
}
P -= dis;
L = stop[i].first;
Q.push(stop[i].second);
}
}
int main()
{
vector<pair<int, int>> stop;
int N;
int L;
int p;
int distance;
int fuel;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> distance >> fuel;
stop.push_back(make_pair(distance, fuel));
}
cin >> L >> p;
cout << function(L, p, stop);
return 0;
}