HD1561The more, The Better(树形DP+有依赖背包)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HD1561The more, The Better(树形DP+有依赖背包)相关的知识,希望对你有一定的参考价值。

The more, The Better

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6765    Accepted Submission(s): 3978


Problem Description
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
 

 

Input
每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。
 

 

Output
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
 

 

Sample Input
3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0
 

 

Sample Output
5 13
 

 

Author
8600
 

 

Source
 

 

Recommend
LL
 
分析:dp[i][j]表示以i节点的子树最多选择j个城市的最大价值
对于i节点选择j个城市,可以从i节点的选择k个城市,从i的子节点选择j - k个城市,状态转移dp[i][j] = max{ dp[ i ][ j ], dp[ i ][ k] + dp[ son[i] ][j - k] }
把0点作为根节点就组成了一颗树,最后所求就是dp[0][m]
技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 const int Max = 220;
 7 struct Node
 8 {
 9     int to;
10     int next;
11 };
12 Node edge[Max];
13 int dp[Max][Max],value[Max],head[Max];
14 int n,m,tol;
15 void add_edge(int a, int b)
16 {
17     edge[tol].to = b;
18     edge[tol].next = head[a];
19     head[a] = tol++;
20 }
21 void init()
22 {
23     tol = 0;
24     memset(head, -1, sizeof(head));
25     memset(dp, 0, sizeof(dp));
26 }
27 void dfs(int u)
28 {
29     dp[u][1] = value[u];
30     for(int i = head[u]; i != -1; i = edge[i].next)
31     {
32         int v = edge[i].to;
33         dfs(v);
34         //每次遍历完一个子节点就更新dp[u][k]
35         //同01背包一样,dp[u][k]保存的是上一个状态所以k要从m开始逆序循环,更新
36         //第一层循环意思就是u节点选择k(m到1)个城市的最大价值
37         for(int k = m; k >= 1; k--)
38         {
39             //第二层循环的意思就是父节点可以选择的个数,因为必选自己节点所以是<;
40             for(int j = 1; j < k; j++)
41             {
42                 dp[u][k] = max(dp[u][k], dp[u][j] + dp[v][k - j]);
43                 //此时dp[u][j]存放的是访问完前一个子节点的状态,当访问完v也就是当前子节点时就要在更新一遍
44                 //以前的选择1个,v节点就选择m - 1个,即前一个状态选择j个,这个子节点就选择k - j个
45             }
46         }
47     }
48 }
49 int main()
50 {
51     while(scanf("%d%d", &n, &m) != EOF)
52     {
53         if(n == 0 && m == 0)
54             break;
55         int a;
56         init();
57         for(int i = 1; i <= n; i++)
58         {
59             scanf("%d%d", &a, &value[i]);
60             add_edge(a, i);
61         }
62         value[0] = 0;
63         m++;
64         dfs(0);
65         printf("%d\n", dp[0][m]);
66     }
67     return 0;
68 }
View Code

 

以上是关于HD1561The more, The Better(树形DP+有依赖背包)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1561 The more, The Better

hdu 1561 The more, The Better(树形dp)

hdu1561The more, The Better(树形背包)

hdu1561 The more, The Better (树形DP)

hdu 1561 The more, The Better 树形dp

HDU1561 The more, The Better(树型DP)