标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 3368 Accepted Submission(s): 1569
对于每个根节点root,有个容量为K的背包
如果它有i个儿子,那么就有i组物品,价值分别为dp[son][0],dp[son][1].....dp[son][k] ,这些物品的重量分别为0,1,.....k
现在要求从每组里选一个物品(且必须选一个物品)装进root的背包,使得容量不超过k的情况下价值最大。
但是这里有一个问题,就是每组必须选一个物品。
我们先将dp[son][0]放进背包,如果该组里有更好的选择,那么就会换掉这个物品,否则的话这个物品就是最好的选择。这样保证每组必定选了一个。
dp[i][j] 表示以i为根节点子树,去j个机器人花费的最小值。
知识
分组背包:
使用一维数组的“分组背包”伪代码如下:
for 所有的组i
for v = V..0
for 所有的k属于组i
f[v]=max{f[v],f[v-c[k]]+w[k]}
AC代码:
1 # include <bits/stdc++.h> 2 using namespace std; 3 const int MAX = 10010; 4 struct node 5 { 6 int to; 7 int val; 8 int next; 9 }tree[MAX * 2]; 10 int head[MAX]; 11 int tol; 12 int dp[MAX][15]; 13 void add(int a, int b, int val) 14 { 15 tree[tol].to = b; 16 tree[tol].val = val; 17 tree[tol].next = head[a]; 18 head[a] = tol++; 19 } 20 int n, s, k; 21 void dfs(int root, int f) 22 { 23 for(int i = head[root]; i != -1; i = tree[i].next) 24 { 25 int son = tree[i].to; 26 if(son == f) 27 continue; 28 dfs(son, root); 29 for(int j = k; j >= 0; j--) 30 { 31 dp[root][j] += dp[son][0] + 2 * tree[i].val; //先将dp[son][0]放进背包 32 for(int l = 1; l <= j; l++) 33 { 34 dp[root][j] = min(dp[root][j], dp[root][j - l] + dp[son][l] + l * tree[i].val); 35 // 更优的方案 36 } 37 } 38 } 39 } 40 int main() 41 { 42 while(scanf("%d %d %d", &n, &s, &k) != EOF) 43 { 44 memset(dp, 0, sizeof(dp)); 45 memset(head, -1, sizeof(head)); 46 tol = 0; 47 for(int i = 1; i < n; i++) 48 { 49 int a, b, val; 50 scanf("%d %d %d", &a, &b, &val); 51 add(a, b, val); 52 add(b, a, val); 53 } 54 dfs(s, -1); 55 printf("%d\n", dp[s][k]); 56 } 57 return 0; 58 }
标签:
原文地址:http://www.cnblogs.com/lyf-acm/p/5796625.html