首先讲一下思路。
这道题是一个贪心算法的题,大体方法就是0.寻找比自己距离远的,到能够到达的最大距离之间的加油站,看他们的油价。如果找到了更低价格的油价,就加油到刚好能到达那个加油站的距离的油,然后去那个更低价格的加油站。如果找不到更低的,就找尽可能低的油价的加油站,在当前加油站加满油之后过去。因为想要让路程上使用的尽可能是低价的油,既然没有比当前更低价格的了,就让油箱加到最大值,这样能保证利益最大化,保证最大的距离使用的是便宜的油。
但有几个要注意的地方。
第一个是终点的处理。基本所有的解答都是将终点当作一个价格为0的车站和距离为最大距离的车站。其实自己写一遍这个题就知道,如果不将终点当做一个车站处理的话,解题将会非常麻烦。因为你需要在判断当前车站能不能直接到终点?不能到的话下一个车站能不能到?都不能的话是不是不存在最终答案?总之很麻烦。
第二个是油箱的问题。第一遍自己写到最后的时候就发现必须要加油箱这个参数,因为如果不加邮箱就会有一个致命的问题:如果在车程内不存在比当钱油价更便宜的车站,那么我的油就要加满,但是我在下一个车站要加多少油呢?因为如果下一个车站就可以到终点了,那么油就只用加刚刚好,如果下一个车站不能到终点,但存在更便宜的车站,那么加的油就还应该是到便宜车站距离的油。
如果想不明白就拿个纸和笔自己写一下,贪心的逻辑还是比较简单的。
还有一个题目默认的点,不存在两个距离一样的车站。
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
struct station
{
double price,dis;
}st[500];
bool cmp1(station a,station b)
{
return a.dis<b.dis;
}
int main()
{
cout<<fixed<<setprecision(2);
double cmax,d,davg;
int n;
cin>>cmax>>d>>davg>>n;
for(int i=0;i<n;i++)
{
cin>>st[i].price>>st[i].dis;
}
st[n].price=0;
st[n].dis=d;
double dmax=cmax*davg;
sort(st,st+n,cmp1);
if(st[0].dis!=0)
cout<<"The maximum travel distance = 0.00";
else
{
double ans=0,nowtank=0;
int now=0;
while(now!=n) //直到终点站
{//如果车程内存在价格更小的车站,直接去,否则下一个车站是价格最小的车站
double minprice=999999999; //选出下一个价格最小的车站
int k=-1; //下一个车站为k号站
for(int j=now+1;j<=n;j++)
{//遍历之后所有在车程范围内车站,如果存在一个更便宜的车站,
//那么加到那个车站距离的油,到下一个车站油箱为0。否则,加满油
//到一个车站时会有剩的站
if(st[j].dis-st[now].dis>dmax) //不存在下一个可以到达的车站了
break;
else
{
if(st[j].price<minprice)
{
minprice=st[j].price;
k=j;
}
if(st[j].price<st[now].price)
{
break;
}
}
}
if(k==-1)
break;
double need=(st[k].dis-st[now].dis)/davg; //这次行程需要的油
if(minprice<st[now].price) //距离内有更便宜的车站
{
if(nowtank<need) //油箱的油是不够的
{
ans+=(need-nowtank)*st[now].price;
nowtank=0;
}
else //油是够的
nowtank-=need;
}
else //不存在这样一个车站
{
ans+=(cmax-nowtank)*st[now].price;
nowtank=cmax-need;
}
now=k;
}
if(now==n)
cout<<ans;
else
cout<<"The maximum travel distance = "<<st[now].dis+dmax;
}
return 0;
}