码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1017 魔兽地图

时间:2015-02-01 23:11:56      阅读:368      评论:0      收藏:0      [点我收藏+]

标签:

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 魔兽地图

标签:

原文地址:http://www.cnblogs.com/mmlz/p/4266214.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!