首页 > 代码库 > HDU 1561 树形DP背包问题
HDU 1561 树形DP背包问题
这是自己第一道背包上树形结构问题,不是很理解这个概念的可以先看看背包九讲
自己第一次做,看了一下别人的思路,结合着对简单背包问题的求解方式自己一次AC了还是有点小激动的
题目大意是:
攻克m个城市,每个城市都有对应数量的宝贝,攻克某一个城市必须保证其对应的某一个特定城市已经被攻克,希望得到最多数量的宝贝
很容易根据题目画出一个对应关系的树形结构,每个节点都有一个对应的宝物的数量
我们用dp[i][j]存 i 号节点它下方子树中 有 j 个城市被攻克时得到的宝物最大数量 , 此时的 i 号是没有被攻克的!
然后通过dfs自底向上更新
1 /* 2 总的u下方子树攻克了j个城市,为当前v姿势分配k个城市攻克 3 添加当前v包含了攻克k-1个子树的城市,要添加子树v必须 4 同时保证v被攻克,所以加上的是dp[v][k-1] + val[v] 5 */ 6 for(int j = m ; j>=1 ; j--){ 7 for(int k = j ; k>0 ; k--){ 8 dp[u][j] = max(dp[u][j] , dp[u][j-k] + dp[v][k-1] + val[v]); 9 }10 }
这里可以理解为当根节点u下方有 j 个城市被攻克时, 若有 k 个城市的攻克来自v的子树, 那么v必然要被攻克 , val[v],不然其下方的城市不能攻克
除去v还有 k -1个v节点对应子树中的城市要攻克 ,也就是 dp[v][k-1]
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int N = 205; 6 7 int dp[N][N] , val[N] , first[N] , k; 8 9 struct Edge{10 int y , next;11 }e[N];12 13 void add_edge(int x , int y)14 {15 e[k].y = y , e[k].next = first[x];16 first[x] = k++;17 }18 19 void dfs(int u , int m)20 {21 for(int i=first[u] ; i!=-1 ; i=e[i].next){22 int v = e[i].y;23 dfs(v , m);24 /*25 总的u下方子树攻克了j个城市,为当前v姿势分配k个城市攻克26 添加当前v包含了攻克k-1个子树的城市,要添加子树v必须27 同时保证v被攻克,所以加上的是dp[v][k-1] + val[v]28 */29 for(int j = m ; j>=1 ; j--){30 for(int k = j ; k>0 ; k--){31 dp[u][j] = max(dp[u][j] , dp[u][j-k] + dp[v][k-1] + val[v]);32 }33 }34 }35 }36 37 int main()38 {39 // freopen("a.in" , "r" , stdin);40 int n , m , a , b;41 while(scanf("%d%d" , &n , &m) , n||m)42 {43 memset(first , -1 , sizeof(first));44 k = 0;45 for(int i=1 ; i<=n ; i++)46 {47 scanf("%d%d" , &a , &b);48 add_edge(a , i);49 val[i] = b;50 }51 memset(dp , 0 , sizeof(dp));52 dfs(0 , m);53 54 printf("%d\n" , dp[0][m]);55 }56 return 0;57 }
HDU 1561 树形DP背包问题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。