HDU1561 The more, The Better(树型DP)

Posted

tags:

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

题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏。

题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP:

  • dp[u][m]表示以u结点为根的子树攻克m个结点的最大价值

但是这样转移太难了,根是从每个孩子通过各自分配若干的城堡去攻克转移的,一个排列组合数,阶乘,是指数级的时间复杂度!

看了题解,原来这是依赖背包,没看背包九讲。。不过网上的博客似乎没说清楚,事实上这个状态应该是三个维度来表示:

  • dp[u][m][n]表示以u结点为根的子树,且只考虑u结点的前n个孩子,去攻克m个结点,所能得到的最大价值
  • 转移就是dp[u][m][n]=max(dp[u][m-k][n-1]+dp[u的第n个孩子][k][u的孩子个数])(0<=k<m)

可以发现n只从n-1转移而来,那么就可以像01背包重复利用内存,这三维数组只用二维数组来实现,即:

  • dp[u][m]=max(dp[u][m-k]+dp[u’][k])(father[u‘]=u,0<=k<m)
  • m要从大到小枚举。

代码感觉还不好实现。。感觉这题挺难的= =虽然听说这是树型DP入门题。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 struct Edge{
 6     int u,v,next;
 7 }edge[222];
 8 int NE,head[222];
 9 void addEdge(int u,int v){
10     edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
11     head[u]=NE++;
12 }
13 int val[222],d[222][222];
14 void dp(int u,int m){
15     d[u][1]=val[u];
16     for(int i=head[u]; i!=-1; i=edge[i].next){
17         int v=edge[i].v;
18         dp(v,m);
19         for(int j=m; j>=2; --j){
20             for(int k=0; k<j; ++k){
21                 d[u][j]=max(d[u][j],d[u][j-k]+d[v][k]);
22             }
23         }
24     }
25 }
26 int main(){
27     int n,m,a;
28     while(~scanf("%d%d",&n,&m) && (n||m)){
29         NE=0;
30         memset(head,-1,sizeof(head));
31         for(int i=1; i<=n; ++i){
32             scanf("%d%d",&a,val+i);
33             addEdge(a,i);
34         }
35         memset(d,0,sizeof(d));
36         dp(0,m+1);
37         printf("%d\n",d[0][m+1]);
38     }
39     return 0;
40 }

 

以上是关于HDU1561 The more, The Better(树型DP)的主要内容,如果未能解决你的问题,请参考以下文章

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)

hdu 1561 The more, The Better (依赖背包 树形dp)