zju pat 1033(2012 浙大复试)

题目的意思就是在一条笔直的路上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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值