HDU 1561 树形DP+有依赖的背包

前端之家收集整理的这篇文章主要介绍了HDU 1561 树形DP+有依赖的背包前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

此题的依赖关系为选子节点必须选其根节点@H_502_1@

可以转换成分组背包,子节点和根在一个分组内,具体参见 背包九讲@H_502_1@

也可见:http://www.cnblogs.com/gentleh/archive/2013/03/19/2969890.html@H_502_1@

代码有注释@H_502_1@


@H_502_1@

  1. #include<st@R_404_410@.h>
  2. #include<string.h>
  3. #include<vector>
  4. using namespace std;
  5. #define maxn 220
  6. vector<int> vec[maxn];
  7. int val[maxn];
  8. int dp[maxn][maxn];//dp[i][j]以i为根节点选j个地方获得的最大值
  9. int n,m;
  10. void init()
  11. {
  12. for(int i=0;i<maxn;i++)
  13. vec[i].clear();
  14. memset(dp,sizeof(dp));
  15. }
  16. void dfs(int rt)
  17. {
  18. dp[rt][1]=val[rt];//选1个必然先它本身
  19. int sz=vec[rt].size();
  20. for(int i=0;i<sz;i++)
  21. {
  22. int v=vec[rt][i];
  23. dfs(v);//递归到根节点
  24. for(int j=m+1;j>=1;j--) //分组背包,j从m+1..1而不是1..m+1是为了满足dp[i]是由dp[i-1]转换而来
  25. {
  26. for(int k=1;k<j;k++)
  27. dp[rt][j]=max(dp[rt][j],dp[rt][j-k]+dp[v][k]);//dp[v][k]构成了一个新节点
  28. }
  29. }
  30. }
  31.  
  32. int main()
  33. {
  34. freopen("in.txt","r",stdin);
  35. while(scanf("%d%d",&n,&m)==2&&(n||m))
  36. {
  37. init();
  38. int i,a,b;
  39. for(i=1;i<=n;i++)//建图,原图为森林,这里把0作为根转换成了树
  40. {
  41. scanf("%d%d",&a,&b);
  42. vec[a].push_back(i);
  43. val[i]=b;
  44. }
  45. val[0]=0;
  46. dfs(0);
  47. printf("%d\n",dp[0][m+1]);//以0为根选m+1个,其中包含0
  48. }
  49. return 0;
  50. }

猜你在找的设计模式相关文章