题目的意思就是在一条笔直的路上500个以内的的加油站,每个加油站分别有自己的油价,有一个体积有限的邮箱,求一个最优的加油策略来确定最小的花费到达终点.
定义一个最远距离为满邮箱跑完的距离,先感觉一下的策略,有两种,一种就是如果在最远距离之内能存在一个加油站比当前的油价便宜,那么就肯定不能买太多邮,否则在那边买肯定更优,还有一点就是如果在最远距离之内没有加油站比当前加油站的价格便宜的话,那么策略就是在这个加油站能卖则多买.
中和以上的想法,我们的算法就是,先预处理出每个店的状态,一种就是尽可能多买,还有一种就是,只买到距离最近的那个加油站的油,然后从第一个加油站开始推,如果当前油比预计的多,就不买,否则就按预想补足油量.
如果加油站的点数比较多的话,那么就可以用单调队列处理第一步的预处理,然后递推一遍,总体的复杂度达到o(n),代码就不贴了...
#include<stdio.h>
#include<stdlib.h>
#define INF 0x3f3f3f3f
int n;
double cmax,d,davg;
int state[510];
struct node
{
double price;
double pos;
};
struct node gas[510];
int cmp(const void *a,const void *b)
{
if((*(struct node *)a).pos > (*(struct node *)b).pos)
return 1;
return -1;
}
void yu()
{
int i,last=n,f;
int minn;
for(i=n-1;i>=0;i--)
{
minn=0;
for(f=last;f>i;f--)
{
if(gas[f].pos-gas[i].pos > davg*cmax)
{
last=f-1;
continue;
}
else
{
if(gas[f].price < gas[i].price)
minn=f;
}
}
if(i == last)
state[f]=-1;
else
state[i]=minn;
}
}
void debug()
{
int i;
for(i=0;i<=n;i++)
printf("%d\n",state[i]);
}
int main()
{
double need,left;
double money,dis;
int i,flag;
scanf("%lf%lf%lf%d",&cmax,&d,&davg,&n);
for(i=0;i<n;i++)
scanf("%lf%lf",&gas[i].price,&gas[i].pos);
gas[n].price=0;
gas[n].pos=d;
qsort(gas,n+1,sizeof(gas[0]),cmp);
if(0 != gas[0].pos)
{
printf("The maximum travel distance = 0.00\n");
return 0;
}
yu();
flag=0;
left=0;
money=0;
for(i=0;i<=n;i++)
{
if(d == gas[i].pos)
{
flag=-1;
break;
}
if(-1 == state[i])
{
dis=gas[i].pos+cmax*davg;
flag=0;
break;
}
else if(0 == state[i])
{
need=cmax-left;
left=cmax;
money+=need*gas[i].price;
left-=(gas[i+1].pos-gas[i].pos)/davg;
}
else
{
need=(gas[state[i]].pos-gas[i].pos)/davg;
if(need > left)
{
need-=left;
money+=need*(gas[i].price);
left=(gas[state[i]].pos-gas[i].pos)/davg;
}
left-=(gas[i+1].pos-gas[i].pos)/davg;
}
}
if(-1 == flag)
printf("%.2lf\n",money);
else
printf("The maximum travel distance = %.2lf\n",dis);
return 0;
}