题目
思路
题目大意:给出一些加油站以及他们各自油的价格,问如何选择加油策略使得总花费最小;
第一步,我们肯定要将加油站的距离按从小到大的顺序排好;
排好后有一种特殊情况特判一下,如果第一个加油站不在起点,那么这个车就哪也去不了,当然应该直接返回;
接下来考虑策略的选择;对一个加油站i来说,我们肯定会去看在当前加油站i加满油的情况下最远到达的加油站内有没有比i更便宜的,这里分为三种情况:
1、如果有比i更便宜的加油站 j (注意,这里需要选第一个比i便宜的加油站),我们就要看此时油箱中的油能不能到达j,如果能继续走;如果不能需要在这个加油站加一点油,使其到达j时恰好消耗完油;
2、如果没有比i更便宜的加油站,就需要选择先到相对最便宜的那个j,此时,需要在当前加油站 i 加满油;这里为什么要加满呢,因为下一个比i便宜的加油站即使加满油了也不能到达,需要先到这个相对便宜点的加油站j补充点油,早晚都得加,况且在i加便宜;
3、如果不能到达任何加油站,直接退出;
代码
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 510;
double C, D, Davg;//油箱容量,总距离,每升油所走距离,加油站数量
int N;
struct node{
double price, dis;
}gas[maxn];
bool cmp(node a, node b){
return a.dis < b.dis;
}
int main()
{
scanf("%lf%lf%lf%d", &C, &D, &Davg, &N);
for(int i = 0; i < N; i ++){
scanf("%lf%lf", &gas[i].price, &gas[i].dis);
}
//将终点输入
gas[N].price = 0, gas[N].dis = D;
sort(gas, gas + N + 1, cmp);//将加油站按距离从小到大排序
//特判第一个加油站不在起点的情况
if(gas[0].dis != 0){
printf("The maximum travel distance = 0.00\n");
return 0;
}
double curCost = 0, curTank = 0;//当前总花费,当前油量
int curGas = 0;//当前所在加油站
while(curGas != N){
//计算从当前加油站加满油出发最远到达的距离
double maxx = C * Davg + gas[curGas].dis;
int nextGas = curGas + 1;//下一目标油站
for(int j = nextGas; gas[j].dis <= maxx; j ++){
//如果找到一个更便宜的加油站
if(gas[j].price < gas[curGas].price){
nextGas = j;
break;
}
//随时更新能到达的最便宜的加油站,以防没有比当前加油站价格更低的
if(gas[j].price < gas[nextGas].price) nextGas = j;
}
//如果即使加满油也没有找到加油站
if(nextGas == curGas + 1 && gas[nextGas].dis > maxx) {
printf("The maximum travel distance = %.2f\n", maxx);
return 0;
}
double need = (gas[nextGas].dis - gas[curGas].dis) / Davg;//从当前到下一加油站所需油量
//下一加油站的价格低于当前价格
if(gas[nextGas].price < gas[curGas].price){
//如果所剩的油不够到达下一加油站,加到够就行
if(curTank < need){
curCost += (need - curTank) * gas[curGas].price;
curTank = need;//加到油够用就行
}
}
else{
curCost += (C - curTank) * gas[curGas].price;
curTank = C;//把油箱加满
}
//未进入下一状态做准备,油箱减少
curTank -= need;
curGas = nextGas;
}
printf("%.2f\n", curCost);
system("pause");
return 0;
}