bzoj1017 [JSOI2008]魔兽地图DotR

1017: [JSOI2008]魔兽地图DotR

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 1230  Solved: 522
[Submit][Status][Discuss]

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,树形DP

状态很容易想Dp[i][j][k] 表示第 i 个点,恰好花去k元其中 必须合成 j 个提供给父亲节点合成用,所能得到的最大力量(不包括提供给父亲的那部分)

转移时维护一个辅助数组F[x][i][j]

表示第 x 个节点,前 i 个孩子, 花去 j 元能获得的最大力量,具体看代码吧,要在枚举提供给父亲节点的数目的前提下计算(废话)

 

综上所述,本题得解

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <deque>
  6 #include <vector>
  7 #include <queue>
  8 #include <iostream>
  9 #include <algorithm>
 10 #include <map>
 11 #include <set>
 12 #include <ctime>
 13 using namespace std;
 14 typedef long long LL;
 15 #define For(i, s, t) for(int i = (s); i <= (t); i++)
 16 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
 17 #define MIT (2147483647)
 18 #define INF (1000000001)
 19 #define MLL (1000000000000000001LL)
 20 #define sz(x) ((bnt) (x).size())
 21 #define clr(x, y) memset(x, y, sizeof(x))
 22 #define puf push_front
 23 #define pub push_back
 24 #define pof pop_front
 25 #define pob pop_back
 26 #define ft first
 27 #define sd second
 28 #define mk make_pair
 29 inline void SetIO(string Name) {
 30     string Input = Name+".in",
 31     Output = Name+".out";
 32     freopen(Input.c_str(), "r", stdin),
 33     freopen(Output.c_str(), "w", stdout);
 34 }
 35 
 36 const int N = 60, M = 2010, Max = 110;
 37 int n, m;
 38 int Root, Dp[N][Max][M], F[N][N][M];
 39 int Fa[N], Need[N][N], Child[N][N], LC[N];
 40 int Power[N], Money[N], Limit[N];
 41 bool Visit[N], Basic[N];
 42 
 43 inline void Input() {
 44     scanf("%d%d", &n, &m);
 45     For(i, 1, n) {
 46         scanf("%d", &Power[i]);
 47         char ch = ' ';
 48         while(ch != 'A' && ch != 'B') ch = getchar();
 49         if(ch == 'A') {
 50             scanf("%d", &LC[i]);
 51             For(j, 1, LC[i]) {
 52                 scanf("%d%d", &Child[i][j], &Need[i][j]);
 53                 Visit[Child[i][j]] = 1;
 54             }
 55         } else {
 56             scanf("%d%d", &Money[i], &Limit[i]);
 57             Limit[i] = min(Limit[i], m/Money[i]), Basic[i] = 1;
 58         }
 59     }
 60 }
 61 
 62 inline void CalnLimit(int x) {
 63     if(Basic[x]) return;
 64     Limit[x] = INF, Money[x] = 0;
 65     For(i, 1, LC[x]) {
 66         int y = Child[x][i];
 67         CalnLimit(y);
 68         Limit[x] = min(Limit[x], Limit[y]/Need[x][i]);
 69         Money[x] += Money[y]*Need[x][i];
 70     }
 71     Limit[x] = min(Limit[x], m/Money[x]);
 72 }
 73 
 74 inline void Search(int x) {
 75     if(Basic[x]) {
 76         For(i, 0, Limit[x])
 77             For(j, i, Limit[x])
 78                 Dp[x][i][j*Money[x]] = (j-i)*Power[x];
 79     } else {
 80         For(i, 1, LC[x]) Search(Child[x][i]);
 81         
 82         For(k, 0, Limit[x]) {
 83             For(i, 0, LC[x])
 84                 For(j, 0, m) F[x][i][j] = -INF;
 85             F[x][0][0] = 0;
 86             
 87             For(i, 1, LC[x])
 88                 For(j, 0, m)
 89                     For(g, 0, j)
 90                         F[x][i][j] = max(F[x][i][j], 
 91                             F[x][i-1][j-g]+Dp[Child[x][i]][k*Need[x][i]][g]);
 92             
 93             For(i, 0, k)
 94                 For(g, 0, m)
 95                     Dp[x][i][g] = max(Dp[x][i][g], F[x][LC[x]][g]+Power[x]*(k-i));
 96         }
 97     }
 98 }
 99 
100 inline void Solve() {
101     For(i, 1, n)
102         if(!Visit[i]) {
103             Root = i;
104             break;
105         }
106     
107     CalnLimit(Root);
108     
109     For(i, 1, n)
110         For(j, 0, Limit[i])
111                 For(k, 0, m) Dp[i][j][k] = -INF;
112     Search(Root);
113     
114     int Ans = 0;
115     For(i, 0, m) Ans = max(Ans, Dp[Root][0][i]);
116     printf("%d\n", Ans);
117 }
118 
119 int main() {
120     SetIO("1017");
121     Input();
122     Solve();
123     return 0;
124 }
View Code

 

posted @ 2015-07-01 19:00  yanzx6  阅读(200)  评论(0编辑  收藏  举报