bzoj 1017[JSOI2008]魔兽地图DotR - 树形dp
1017: [JSOI2008]魔兽地图DotR
Time Limit: 30 Sec Memory Limit: 162 MBDescription
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
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
好神的dp!
因为装备的合成路线是一棵树,所以我们可以套用树形dp.
我们设状态 f[i][j][k] 表示 到了第i个装备有j个用于向上合成一共花费k元能得到的最大力量
转移时我们枚举每个装备的购买数量L
g[i][j] 表示到第i个儿子花了j元的最大力量
g[i][j]可以用背包转移
f[i][j][k] = g[last son][k] + (L - j) * p[i];
然而复杂度很玄学,要加一个剪枝
v[i] 是装备合成的总价格, l[i] 表示i的最大上限
l[i] = min(l[son] / 合成所需, M / v[i]);
于是就过了。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #define LL long long 7 8 using namespace std; 9 10 const int MAXN = 100, MAXM = 3000; 11 int N, M; 12 int cnt = 0; 13 int ans[MAXN][MAXM]; 14 int maxn; 15 int head[MAXN]; 16 int p[MAXN]; 17 int v[MAXN]; 18 int l[MAXN]; 19 int in[MAXN]; 20 int f[MAXN][MAXN][MAXM]; 21 int gg[MAXN][MAXM]; 22 23 struct edge { 24 int need; 25 int v; 26 int next; 27 } g[MAXM * 2]; 28 char kind[100][10]; 29 30 void addedge(int u, int v, int w) 31 { 32 g[++cnt].v = v; 33 g[cnt].next = head[u]; 34 g[cnt].need = w; 35 head[u] = cnt; 36 } 37 inline LL read() 38 { 39 LL x = 0, w = 1; char ch = 0; 40 while(ch < '0' || ch > '9') { 41 if(ch == '-') { 42 w = -1; 43 } 44 ch = getchar(); 45 } 46 while(ch >= '0' && ch <= '9') { 47 x = x * 10 + ch - '0'; 48 ch = getchar(); 49 } 50 return x * w; 51 } 52 53 void DFS(int x) 54 { 55 if(kind[x][0] == 'A') { 56 l[x] = MAXN; 57 for(int j = head[x]; j; j = g[j].next) { 58 int to = g[j].v; 59 DFS(to); 60 v[x] += v[to] * g[j].need; 61 l[x] = min(l[x], l[to] / g[j].need); 62 } 63 l[x] = min(l[x], M / v[x]); 64 for(int L = l[x]; L >= 0; L--) { // 枚举x装备购买数量 65 int tot = 0; 66 memset(gg, -0x3f3f3f3f, sizeof gg); 67 gg[0][0] = 0; 68 for(int j = head[x]; j; j = g[j].next) { 69 ++tot; 70 int to = g[j].v; 71 for(int m = 0; m <= M; m++) { 72 for(int k = 0; k <= m; k++) { 73 gg[tot][m] = max(gg[tot][m], gg[tot - 1][k] + f[to][L * g[j].need][m - k]); 74 } 75 } 76 } 77 for(int k = 0; k <= M; k++) { 78 for(int j = 0; j <= L; j++) { 79 f[x][j][k] = max(f[x][j][k], gg[tot][k] + (L - j) * p[x]); 80 } 81 } 82 } 83 } else { 84 for(int L = 0; L <= min(M / v[x], l[x]); L++) { 85 for(int j = 0; j <= L; j++) { 86 f[x][j][v[x] * L] = (L - j) * p[x]; 87 } 88 } 89 } 90 } 91 int main() 92 { 93 // freopen("t.out", "w", stdout); 94 memset(f, -0x3f3f3f3f, sizeof f); 95 N = read(), M = read(); 96 for(int i = 1; i <= N; i++) { 97 p[i] = read(); 98 scanf("%s", kind[i]); 99 if(kind[i][0] == 'A') { 100 int C = read(); 101 for(int j = 1; j <= C; j++) { 102 int v = read(), w = read(); 103 in[v]++; 104 addedge(i, v, w); 105 } 106 } else { 107 v[i] = read(), l[i] = read(); 108 } 109 } 110 int tot = 0; 111 for(int i = 1; i <= N; i++) { 112 if(!in[i]) { 113 ++tot; 114 DFS(i); 115 for(int j = 0; j <= M; j++) { 116 for(int k = 0; k <= j; k++) { 117 //for(int t = 0; t <= l[t]; t++) { 118 ans[tot][j] = max(ans[tot][j], ans[tot - 1][k] + f[i][0][j - k]); 119 //} 120 } 121 } 122 } 123 } 124 for(int i = 0; i <= M; i++) { 125 maxn = max(ans[tot][i], maxn); 126 } 127 printf("%d\n", maxn); 128 return 0; 129 } 130 131 /* 132 133 10 59 134 5 A 3 6 1 9 2 10 1 135 1 B 5 3 136 1 B 4 3 137 1 B 2 3 138 8 A 3 2 1 3 1 7 1 139 1 B 5 3 140 5 B 3 3 141 15 A 3 1 1 5 1 4 1 142 1 B 3 5 143 1 B 4 3 144 145 */