一道贪心题,一直过不了,看了其他人的思路,发现依然是数学太差的锅,逻辑混乱,不能考虑到所有情况。
思路如下:
- 预处理:添加费用为0,距离为终点的加油站,然后以距离和费用为标准进行排序;
- 假设当前在下标为[i]的加油站,寻找所能到达的最大距离范围内的价格最低的加油站,如果遇到比当前加油站费用低的加油站,立刻结束寻找,否则直到寻找到范围内最优解;
- 根据第(2)步的结果分情况计算
- 如果没找到,说明当前所在加油站到不了下一个最近的加油站,计算加满油所能到达的最大距离,结束;
- 如果找到的加油站价格比当前加油站的价格低,则只加到正好到达下一个加油站的油,并计算费用,更新当前位置并计算余油(余油为0),重复步骤(2);
- 如果找到的加油站价格比当前加油站的价格高,则在当前加油站加满油,并计算费用,更新当前位置并计算余油,重复步骤(2);
- 如果更新完位置之后,发现已经到达终点,则结束;
另外今天发现了Dev一个非常方便的快捷键:整体代码缩进对齐 Ctrl+Shift+A
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct Gas_station {
double prise;
int pos;
bool operator<(const Gas_station& g) {
if(pos<g.pos)
return true;
else if(pos==g.pos&&prise<g.prise)
return true;
else
return false;
}
} Gas;
Gas gas[510];
int main() {
int c, d, ad, n;
cin >> c >> d >> ad >> n;
for (int i = 0; i < n; i++) {
cin>>gas[i].prise>>gas[i].pos;
}
//添加一个终点加油站以方便判断
gas[n].prise=0;
gas[n].pos=d;
sort(gas,gas+n);
//位置 下一个最大位置 当前加油站下标 花费 余油
int npos=0;
int maxpos=c*ad;
int ngas=0;
double cost=0;
double g=0;
int i=0;//下标
if(gas[0].pos==0) {
while(true) {
bool flag=false;
int mcpost=i;
//寻找范围之内最便宜加油站
while(gas[i].pos<=maxpos&&i<=n) {
flag=true;
if(gas[i].prise<gas[mcpost].prise)
mcpost=i;
if(gas[i].prise<gas[ngas].prise)
break;
i++;
}
if(flag) {
if(gas[mcpost].prise<=gas[ngas].prise) {
if((gas[mcpost].pos-npos)*1.0/ad>g) {
cost+=(((gas[mcpost].pos-npos)*1.0/ad-g)*gas[ngas].prise);
g=0;
} else {
g-=(gas[mcpost].pos-npos)*1.0/ad;
}
} else {
cost+=(c-g)*gas[ngas].prise;
g=c-(gas[mcpost].pos-npos)*1.0/ad;
}
i=mcpost+1;
ngas=mcpost;
npos=gas[mcpost].pos;
maxpos=npos+c*ad;
if(npos==d)
break;
} else {
cost+=(c-g)*gas[ngas].prise;
npos+=c*ad;
break;
}
}
}
//根据不同情况输出结果
if(npos==d)
printf("%.2f",cost);
else
printf("The maximum travel distance = %.2f",(double)npos);
return 0;
}