思路:
题目要求求出最少的花费(能到达终点的情况),或者求出能走过的最大距离(如果不能到达)。
如果可以到达终点,就需要让每次走的路的花费都是最低的,保证每段距离的耗油价格最低就要保证这段距离的
油价最低,将终点视为一个pri=0,dis=d的油站节点,然后将距离从小到大排序(保证这个节点i之后的节点j都在i前面),
所以从起始节点st开始找下一个能够到达的距离L,然后查找st与L之间的节点中比st油价低的节点,这一次就走到它就行了(贪心),如果没有找到且还没有到达终点,说明永远也到达不了终点了(cur[now].dis+mx就是可以到达的最大距离)。
如果最终走到终点n,说明可以到达终点,否则不行。
反思:
从0-d距离内的最短花费可以视为从一个从0-x的最少花费,所以不断更新x,直到x==d时,就求出最少花费了,
也就是贪心的由局部最优解得到最优解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100100;
struct Node{
double dis,pri;
}cur[maxn];
bool cmp(Node a,Node b)
{
return a.dis<b.dis;
}
int main(void)
{
double cmx,d,dav;
int n,i,j;
scanf("%lf%lf%lf%d",&cmx,&d,&dav,&n);
for(i=0;i<n;i++) scanf("%lf%lf",&cur[i].pri,&cur[i].dis);
cur[n].dis=d;cur[n].pri=0;
sort(cur,cur+n+1,cmp);
if(cur[0].dis!=0){
printf("The maximum travel distance = 0.00\n");
return 0;
}
int now=0;
double tmp=0,ans=0,mx=cmx*dav;
while(now<n){
double mi=99999999;
j=-1;
for(i=now+1;i<=n&&cur[i].dis-cur[now].dis<=mx;i++){
if(mi>cur[i].pri){
j=i;
mi=cur[i].pri;
if(mi<cur[now].pri) break;
}
}
if(j<0) break;
double need=(cur[j].dis-cur[now].dis)/dav;
if(mi<cur[now].pri){
if(need<tmp){
tmp-=need;
}
else{
ans+=(need-tmp)*cur[now].pri;
tmp=0;
}
}
else{
ans+=(cmx-tmp)*cur[now].pri;
tmp=cmx-need;
}
now=j;
}
if(now==n) printf("%.2lf\n",ans);
else printf("The maximum travel distance = %.2lf\n",cur[now].dis+mx);
return 0;
}