HDOJ (HDU) 1561 The more, The Better (树形DP)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1561
很明显这是个分组的有依赖的背包问题(背包问题的扩展请参考 Tianyi Cui 的背包九讲 http://love-oriented.com/pack/ )。
构建树:若攻击城堡 a 要先攻击城堡 b,则 a 是 b 的儿子,这样构建以后是一个森林,添加一个宝物数量为0的节点作为整个森林的树根以后就是一颗树了。
递推方程:设 dp[a][b] 表示以 a 为根节点的子树,要攻击 b 个城堡所获得的最大金钱数目。其中 a 城堡是已经攻下来的。
则 dp[a][b] = max( dp[a][b], dp[a][b - k] + dp[ son(a) ][k] ) ,其中son(a) 表示 a 的儿子节点。
递推方程的意思是:在 a 的子节点子树中选k个点加上a 子树选 b-k 个点 与直接在 a 子树选b个点谁更优。
(其实背包问题或者类背包问题都有相似的递推方程)
初始化:dp[][] 开始均初始化为0,且dp[a][1] 均初始化为节点 a 的宝物数量。
注意细节:算法的第二层循环(代码24行)为什么b要从大到小:dp[root][b] 是由dp[root][b - k] 和 dp[tree[root][i]][k]决定,表面上看b应该从小到大循环,但是从最外层循环(代码21行)来看,
每遍历完一个儿子,dp[root][]都被计算了一遍,在遍历下一儿子时,dp[root][b] 是由遍历上次儿子时已经计算好的dp[root][b - k] 和 dp[tree[root][i]][k]决定,若从小到大循环,则上次计算好的
dp[root][b - k]就被覆盖了。
废话少说,上代码:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 using namespace std; 5 6 const int SIZE = 201; 7 int max(int a, int b) 8 { 9 return a>b ? a:b; 10 } 11 ////////////////////////////////////////////////////////////////////// 12 vector<int> tree[SIZE]; //tree[i][j]表示节点i的第j个儿子的id 13 bool visit[SIZE]; //树节点是都访问过 14 int dp[SIZE][SIZE]; 15 int N,M; 16 17 void dfs_dp(int root) //tree dp 18 { 19 if(visit[root])return; 20 visit[root] = true; 21 for(int i = 0; i < tree[root].size(); i++)//遍历所有儿子 22 { 23 if(!visit[tree[root][i]])dfs_dp(tree[root][i]); //深度优先 24 for(int b = M; b > 1; b--) //循环变量 b 一定是从大到小!!!!!!!!!! 25 for(int k = 1; k < b; k++) 26 { 27 dp[root][b] = max(dp[root][b], dp[root][b - k] + dp[tree[root][i]][k]); 28 } 29 } 30 } 31 32 //将id=0的节点视为整个树的根,其宝物数量为 0; 33 int main() 34 { 35 while((cin>>N>>M) && (N || M)) 36 { 37 //init 38 for(int i = 0; i < SIZE; i++) 39 tree[i].clear(); 40 memset(visit, 0, sizeof(visit)); 41 memset(dp, 0, sizeof(dp)); 42 43 int father,val; 44 for(int i = 1; i <= N; i++) 45 { 46 cin>>father>>val; 47 tree[father].push_back(i); 48 dp[i][1] = val; 49 } 50 51 M++; //由于添加了0号节点为树根,所以,相当于多加了个城堡,且这个城堡必须攻克 52 dfs_dp(0); 53 cout<<dp[0][M]<<endl; 54 } 55 56 return 1; 57 }
【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/archive/2013/06/15/3137679.html