首页 > 代码库 > BZOJ 1017 魔兽地图

BZOJ 1017 魔兽地图

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

HINT

 

Source

很明显的树形dp。开始我不会d,所以准备照着hzwer的copy,后来弄懂了树p的真谛,天黑都不怕了。

树p一般都要开dp两次,通过第一个dp结果来dp第二个,再根据第二个来更新第一个(等于第二个dp只是个桥梁吧)。

像这一题,f[i][j][k]表示i物品贡献给父亲j个花了k的最大力量,通过g数组来完成转移。g[i][k]表示考虑前i个儿子,花j的最大费用,单其实只要一维就够了,因为它可以滚动使用。

如果实在是听不的话,看代码就行了。我就是看代码才理解的。

技术分享
  1 #include<iostream>  2 #include<cstring>  3 #include<vector>  4 #include<cstdio>  5 #include<algorithm>  6 #include<cstdlib>  7 using namespace std;  8   9 #define inf (1<<29) 10 #define maxn 60 11 #define maxm 2010 12 #define maxl 110 13 int n,m,con[maxn],pri[maxn],lim[maxn]; 14 int f[maxn][maxl][maxm],g[maxm],root,ans; 15 bool bas[maxn]; 16 vector < pair <int,int> > need[maxn]; 17  18 inline int Max(int a,int b) { if (a > b) return a; return b; } 19  20 inline int Min(int a,int b) { if (a < b) return a; return b; } 21  22 inline int getint() 23 { 24     int x=0,f=1;char ch=getchar(); 25     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} 26     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} 27     return x*f; 28 } 29  30 inline void read() 31 { 32     for (int i = 1;i <= n;++i) 33     { 34         con[i] = getint(); 35         char opt = getchar(); 36         if (opt == A) 37         { 38             int nn = getint(); 39             for (int j = 1;j <= nn;++j) 40             { 41                 int a = getint(),b = getint(); 42                 need[i].push_back(make_pair(a,b));  43                 bas[a] = true; 44             } 45             lim[i] = inf; 46         } 47         else pri[i] = getint(),lim[i] = getint(); 48     } 49     for (int i = 1;i <= n;++i) 50         if (!bas[i]) { root = i; break; } 51 } 52  53 inline void dp(int now) 54 { 55     if (need[now].size() == 0) 56     { 57         lim[now] = Min(lim[now],m/pri[now]); 58         for (int i = 0;i <= lim[now];++i) 59             for (int j = i;j <= lim[now];++j) 60                 f[now][i][j*pri[now]] = (j-i)*con[now]; 61         return; 62     } 63     lim[now] = inf; int nn = need[now].size(); 64     for (int i = 0;i < nn;++i) 65         dp(need[now][i].first),lim[now] = Min(lim[now],lim[need[now][i].first]/need[now][i].second); 66     for (int i = 0;i <= lim[now];++i) f[now][i][0] = 0; 67     for (int i = 0;i < nn;++i) 68         for (int j = 0;j <= lim[now];++j) 69         { 70             memcpy(g,f[now][j],sizeof(g)); 71             memset(f[now][j],-1,sizeof(g)); 72             for (int k = m;k >= 0;--k) 73             { 74                 for (int r = k;r >= 0; --r) 75                     if (g[k - r] != -1&&f[need[now][i].first][j*need[now][i].second][r] != -1) 76                     { 77                         f[now][j][k] = Max(f[now][j][k],g[k-r]+f[need[now][i].first][j*need[now][i].second][r]); 78                         ans = Max(ans,f[now][j][k]); 79                     } 80             } 81         } 82     for (int i = 0;i <= lim[now];++i) 83         for (int j = i;j <= lim[now];++j) 84             for (int k = 0;k <= m;++k) 85             { 86                 if (f[now][j][k] == -1) continue; 87                 f[now][i][k] = Max(f[now][i][k],f[now][j][k] + (j-i)*con[now]),ans = Max(ans,f[now][i][k]); 88             } 89 } 90  91 int main() 92 { 93     freopen("1017.in","r",stdin); 94     freopen("1017.out","w",stdout); 95     memset(f,-1,sizeof(f)); 96     scanf("%d %d",&n,&m); 97     read(); 98     dp(root); 99     printf("%d",ans);100     fclose(stdin); fclose(stdout);101     return 0;102 }
View Code

 

BZOJ 1017 魔兽地图