0x00 题目地址
To Fill or Not to Fill__牛客网 (nowcoder.com)
0x01 分析
符合最优子结构、无后效性、重复子问题三个条件,因此可以使用贪心求解。
先按照距离排序,将加油站排成一条线。
算法每一步的思路:
1.首先判断油箱加满时的最大里程能否支撑到下一个加油站。(只需判断相邻的油站距离是否大于加满油的最大里程即可,不满足的话就可以输出最大路程,然后return 0)
2.其次,寻找(current_location,current_location+最大里程]内油价最便宜的加油站
2.1 若这个最便宜的油价甚至比当前加油站的更便宜,则只需确保油箱的油足够到下一站即可。
2.1.1 可能油箱本来油量就够,那就不需要加
2.1.2 若油箱的油量不够,那么就加到足够到该加油站的油量即可,不需要多加。
2.2 若这个最便宜的油价比当前加油站的还要贵。那么就在当前的加油站加满油。
最终判断路程是否==距离。然后打印输出总花费即可。
0x02 完整代码
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct station {
double price;
double dis;
};
bool compare(station A, station B) {
if (A.dis == B.dis) {
return A.price < B.price;
}
return A.dis < B.dis;
}
int main() {
double cmax, d, davg, n;
while (cin >> cmax >> d >> davg >> n) {
vector<station> station(n + 1);
for (int i = 0; i < n; ++i)
{
cin >> station[i].price >> station[i].dis;
}
//将终点也作为加油站
station[n].price = 0; //将终点站也看成加油站
station[n].dis = d;
sort(station.begin(), station.end(), compare);
double maxrun = cmax * davg; //最大里程
double run = 0; //路程
double cost = 0; //总花费
double fuel = 0; //当前油箱的油量
for (int i = 0; i < n; i++) {
if ((station[i + 1].dis - station[i].dis )> maxrun) {
printf("The maximum travel distance = %.2f\n", run + maxrun);
return 0;
}
//寻找可行使区间内最便宜的加油站
double cheapest = i+1;
//寻找比当前的加油站油价还便宜的加油站
double nearest = i+1;
for (int j = i + 1; j < n + 1 && station[i].dis + maxrun >= station[j].dis; j++) {
if (station[cheapest].price >= station[j].price) {
cheapest = j;
}
if (station[j].price <= station[i].price) {
nearest = j;
break;
}
}
if (station[cheapest].price > station[i].price) { //当前的油价比后面区间内的油价都便宜,则直接加满
cost += station[i].price * (cmax- fuel);
fuel = cmax;
run += station[cheapest].dis - station[i].dis;
fuel -= (station[cheapest].dis - station[i].dis) / davg; //减去到下一个加油站的油耗
i = cheapest - 1; //要-1,因为for循环还有个i++
}
else { //油价比当前的站还便宜,只需加够足够支撑到下一加油站的油量即可
//看看剩余的油箱是否能跑到那个站
if (fuel < (station[nearest].dis - station[i].dis) / davg) { //如果跑不到下一个站,那就加适量的油
cost += station[i].price * ((station[nearest].dis - station[i].dis) / davg - fuel);
fuel = (station[nearest].dis - station[i].dis) / davg;
}
fuel -= (station[nearest].dis - station[i].dis) / davg; //减去到下一个加油站的油耗
run += station[nearest].dis - station[i].dis;
i = nearest - 1;
}
}
if (run == d) {
printf("%.2f\n", cost);
}
}
return 0;
}