最近打算刷刷NOIP原题,这是第一道,贪心+模拟(+递归),优先队列也能做。
贪心思路炒鸡简洁:
对于当前所处的加油站,枚举统计出所有可以抵达的加油站,记录油价最低值。若最低值小于当前加油站油价,则在当前加油站加上正好可以到达那个加油站的油。若最低值大于当前加油站油价,判断能否从当前加油站直达终点,能就直接去,否则加满油到最低值加油站。
正确性证明:
最低值小于当前加油站时直接到达可达范围内油价最小的加油站正确性显然。
大于时能直达终点则直达终点正确性更显然。否则加满油,可以保证以当前范围内最低油价行进最远距离,不论下一站到哪里,以当前站油价行驶的总路程不变,因此下一站的油价越低越好。
代码:
#include<cstdio>
#include<iostream>
using namespace std;
double d[10],pi[10];
int main()
{
double d1,c,d2,p,pmin=1000,l=0,ans=0;
int n;
cin>>d1>>c>>d2>>p>>n;
d[0]=0;
double d0=0;
pi[0]=p;
double x=c*d2;
for(int i=1;i<=n;i++)
{
cin>>d[i]>>pi[i];
}
for(int i=1;i<=n;i++)
if(d[i]-d[i-1]>x)
{
cout<<"No Solution";
return 0;
}
int ii=0;
while(d1-d0)
{
for(int i=ii+1;d[i]-d0<=x&&i<=n;i++)
if(pi[i]<pmin)
{
pmin=pi[i];
ii=i;
}
if(pmin<=p)
{
ans+=((d[ii]-d0)/d2-l)*p;
l=(d[ii]-d0)/d2;
}
else if(d1-d0>x)
{
ans+=(c-l)*p;
l=c;
}
else
{
ans+=((d1-d0)/d2-l)*p;
break;
}
l=l-(d[ii]-d0)/d2;
d0=d[ii];
p=pmin;
pmin=1000;
}
printf("%.2lf",ans);
return 0;
}