codevs天梯 选菜

 在小松宿舍楼下的不远处,有PK大学最不错的一个食堂——The Farmer’s Canteen(NM食堂)。由于该食堂的菜都很不错,价格也公道,所以很多人都喜欢来这边吃饭。The Farmer’s Canteen的点菜方式如同在超市自选商品一样,人们从一个指定的路口进去,再从一个指定的路口出来并付款。由于来这里就餐的人数比较多,所以人们自觉地在进入口的时候就排成一个长队,沿着长长的摆放着各式各样佳肴的桌子进行选菜。

       小松发现,这种选菜方式意味着,他不能在选菜的时候离开队伍去拿一些他已经看过了的菜或者没有看过的菜,因为插队是不礼貌的,也是被BS的。

       每个菜有一个价值,而小松也自己给每个菜定了一个在他看来的美味价值,例如红烧小黄鱼在小松看来是美味价值很高的,而花菜在小松眼里则是美味价值极低的菜肴。而有一些菜是营养价值极其高的菜(例如米饭),所以无论它的美味价值是多少,小松都会选择1份。现在小松带了X元钱来食堂就餐,他想知道,在不欠帐的情况下,他选菜的美味价值总合最大是多少。

分析:其实这题就是蛮无脑的双关键字的01背包,只是在预处理时将小数化整数(不化整数精度会爆掉==)。

var 

    n,k,i,j,lim,tot,tmp1,kind,ans:longint;

    tmp,lim1:extended;

    f:array[0..1000,0..1000] of longint;

    a,bh,cost,value:array[0..1000] of longint;

    map:array[0..100] of boolean;

begin

  read(n,k,lim1);

  fillchar(map,sizeof(map),0);

  lim:=round(lim1*10);

  for i:=1 to n do begin read(tmp);cost[i]:=round(tmp*10); end;

  for i:=1 to n do begin read(tmp);value[i]:=round(tmp*10);end;

  for i:=1 to n do

    begin

      read(kind);

      if not map[kind] then

        begin

          map[kind]:=true;

          inc(tot);

          a[tot]:=i;

          bh[kind]:=tot;

        end;

    end;

  ans:=0;

  for i:=1 to k do

    begin

      read(tmp1);

      inc(ans,value[a[bh[tmp1]]]);

      value[a[bh[tmp1]]]:=0;

      dec(lim,cost[a[bh[tmp1]]]);cost[a[bh[tmp1]]]:=lim+1;

    end;

  for i:=1 to tot do

    begin

      for j:=1 to lim do

        begin

          f[i,j]:=f[i-1,j];

          if j>=cost[a[i]]

            then if f[i,j]

              f[i,j]:=f[i-1,j-cost[a[i]]]+value[a[i]];

        end;

    end;

  if round((f[tot,lim]+ans)/10)=(f[tot,lim]+ans)/10

    then writeln((f[tot,lim]+ans)/10:0:0)

    else writeln((f[tot,lim]+ans)/10:0:1);

end.


你可能感兴趣的:(动态规划)