Description

DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars。DotR里面的英雄只有一个属性——力量。他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力量值之和。装备分为基本装备和高级装备两种。基本装备可以直接从商店里面用金币购买,而高级装备需要用基本装备或者较低级的高级装备来合成,合成不需要附加的金币。装备的合成路线可以用一棵树来表示。比如,Sange and Yasha的合成需要Sange, Yasha和Sange and Yasha Recipe Scroll三样物品。其中Sange又要用Ogre Axe, Belt of Giant Strength 和 Sange Recipe Scroll合成。每件基本装备都有数量限制,这限制了你不能无限制地合成某些性价比很高的装备。现在,英雄Spectre有M个金币,他想用这些钱购买装备使自己的力量值尽量高。你能帮帮他吗?他会教你魔法Haunt(幽灵附体)作为回报的。
Input

输入文件第一行包含两个整数,N (1 <= n <= 51) 和 m (0 <= m <= 2,000)。分别表示装备的种类数和金币数。装备用1到N的整数编号。接下来的N行,按照装备1到装备n的顺序,每行描述一种装备。每一行的第一个正整数表示这个装备贡献的力量值。接下来的非空字符表示这种装备是基本装备还是高级装备,A表示高级装备,B表示基本装备。如果是基本装备,紧接着的两个正整数分别表示它的单价(单位为金币)和数量限制(不超过100)。如果是高级装备,后面紧跟着一个正整数C,表示这个高级装备需要C种低级装备。后面的2C个数,依次描述某个低级装备的种类和需要的个数。
Output

第一行包含一个整数S,表示最多可以提升多少点力量值。
Sample Input
10 59
5 A 3 6 1 9 2 10 1
1 B 5 3
1 B 4 3
1 B 2 3
8 A 3 2 1 3 1 7 1
1 B 5 3
5 B 3 3
15 A 3 1 1 5 1 4 1
1 B 3 5
1 B 4 3

Sample Output
33

 

看见我机房的小伙伴没写,我又不能问他,BZOJ上这又不是一道不可做题,不想跳过这道题,于是就写了

题解一共也就两种,一个是VFleaKing的,另一个是普通的树dp

看题解看不懂啊,囧,没办法,我就是这么弱........

于是先打暴力,f[i,j,k]表示节点i买了j个,用了k元钱的最大力量值

然后树dp之,对于每一个j,先强制买好j个i物品,然后k元钱里剩下的去做背包(从i的儿子里面选,用合成剩余的部分来做01背包)

暴力好不容易打出来(细节没注意,囧,写了一两个小时暴力,之前还想抄C++代码,可惜不怎么懂,勉强翻译过来连样例都过不了)

暴力肯定是要超时的(我自测,有的点100s都跑不出),不过我发现了一个优化

  1 const
  2         maxn=52;
  3         maxm=2001;
  4 var
  5         w,gold,lim,num,max1,fa,first:array[0..maxn]of longint;
  6         next,last:array[0..maxn*2]of longint;
  7         f:array[0..maxn,0..101,0..maxm]of longint;
  8         n,m,ans,tot:longint;
  9 
 10 procedure insert(x,y,z:longint);
 11 begin
 12         inc(tot);
 13         last[tot]:=y;
 14         next[tot]:=first[x];
 15         first[x]:=tot;
 16         num[tot]:=z;
 17         fa[y]:=x;
 18 end;
 19 
 20 function max(x,y:longint):longint;
 21 begin
 22         if x>y then exit(x);
 23         exit(y);
 24 end;
 25 
 26 function min(x,y:longint):longint;
 27 begin
 28         if x<y then exit(x);
 29         exit(y);
 30 end;
 31 
 32 procedure dfs(x:longint);
 33 var
 34         i,j,k,l,v:longint;
 35 begin
 36         if first[x]=0 then
 37           begin
 38             max1[x]:=min(lim[x],m div gold[x]);
 39             for i:=1 to max1[x] do
 40               begin
 41                 f[x,i,i*gold[x]]:=w[x]*i;
 42                 ans:=max(ans,f[x,i,i*gold[x]]);
 43               end;
 44             exit;
 45           end;
 46         max1[x]:=maxm;
 47         i:=first[x];
 48         while i<>0 do
 49           begin
 50             dfs(last[i]);
 51             max1[x]:=min(max1[x],max1[last[i]] div num[i]);
 52             inc(gold[x],num[i]*gold[last[i]]);
 53             i:=next[i];
 54           end;
 55         for i:=0 to max1[x] do
 56           begin
 57             l:=first[x];
 58             for j:=i*gold[x] to m do
 59               f[x,i,j]:=w[x]*i;
 60             l:=first[x];
 61             while l<>0 do
 62               begin
 63                 for j:=m downto i*gold[x] do
 64                   for k:=num[l]*i to max1[last[l]] do
 65                     for v:=(k-num[l]*i)*gold[last[l]] to j-i*gold[x] do
 66                       f[x,i,j]:=max(f[x,i,j],f[x,i,j-v]+f[last[l],k,v+num[l]*i*gold[last[l]]]-num[l]*i*w[last[l]]);
 67                 l:=next[l];
 68               end;
 69             for j:=i*gold[x] to m do
 70               ans:=max(ans,f[x,i,j]);
 71           end;
 72 end;
 73 
 74 procedure main;
 75 var
 76         i,j,k,x,y:longint;
 77         s:char;
 78 begin
 79         read(n,m);
 80         for i:=1 to n do
 81           begin
 82             read(w[i]);
 83             read(s,s);
 84             if s='B' then read(gold[i],lim[i])
 85             else
 86               begin
 87                 read(k);
 88                 for j:=1 to k do
 89                   begin
 90                     read(x,y);
 91                     insert(i,x,y);
 92                   end;
 93               end;
 94           end;
 95         for i:=1 to n do
 96           if fa[i]=0 then dfs(i);
 97         writeln(ans);
 98 end;
 99 
100 begin
101         main;
102 end.
暴力

相关文章: