HDU 1561 The more, The Better 经典树形DP
2013-10-29 19:39
387 查看
The more, The Better
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4442 Accepted Submission(s): 2639
[align=left]Problem Description[/align]
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
[align=left]Input[/align]
每个测试实例首先包括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输入结束。
[align=left]Output[/align]
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
5
13
这是一道经典的树形DP,去年去凤凰之前就碰到过这道题目了。但是没有看懂思路。
额额,居然拖到现在.
思路:
一看就感觉是背包,还加上了限定个数的条件 M 。
而且,存在依赖关系。装子节点的前提是,把其父亲节点也要装进去才行。
这样的情况,感觉挺难的。
1. dp[ k ][ j ] 代表 对于 k 节点,收集了 j 个 其子节点的最大价值。
是否,要采取对 叶子节点 和 非叶子节点 来进行分类讨论呢?
不是的,更加题意的依赖关系。
我们能得到一个共性的初始化。
dp[ k ][ 0 ]=0;
dp[ k ][ 1 ]=val[k];//这个是要的,只有把自己装进去了,才能装你子节点呀。
递推公式:
dp[ k ][ j ] = max( dp[ k ][ j ] , dp[ dp[k].next[i] ][ j-x ] + dp[ k ][ x ] );
dp[ dp[k].next[i] ][ j-x ] 表示在 k 节点 的 某个子节点里 收集 j-x 个节点。
dp[ k ][ x ] 表示在 k 节点 里 收集 x 个节点。
2. 寻找根节点,我们发现,有许多的森林。那么我用0来做根节点。自然 m++;
3. 最后一个问题是如何书写这个背包了。
for( i=1; i<= f[k].num; i++)//枚举多有少的节点。
{
t=f[k].next[i];
dfs(t); //搜索,实现递归。
for(j=m;j>=2;j--)// 不会表达。囧... 枚举该节点能收集的个数。
{
for(s=1;s<=j;s++)//枚举其该儿子节点 t 收集的个数。
{
dp[k][j]=Max(dp[k][j],dp[t][j-s]+dp[k][s]);
}
}
}
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; int n,m; struct node { int next[202]; int num; }f[202]; int dp[202][202]; int Max(int x,int y) { return x>y? x:y; } void dfs(int k) { int i,j,t,s; dp[k][0]=0; for(i=1;i<=f[k].num;i++)//枚举每一个点 { t=f[k].next[i]; dfs(t); for(j=m;j>=2;j--)//枚举 { for(s=1;s<=j;s++) { dp[k][j]=Max(dp[k][j],dp[t][j-s]+dp[k][s]); } } } } int main() { int i,x; while(scanf("%d%d",&n,&m)>0) { if(n==0&&m==0)break; memset(dp,0,sizeof(dp)); for(i=0;i<=200;i++) f[i].num=0; for(i=1;i<=n;i++) { scanf("%d%d",&x,&dp[i][1]); f[x].num++; f[x].next[f[x].num]=i; } m++; dfs(0); printf("%d\n",dp[0][m]); } return 0; }
/*
如何保证 子节点 装进去的前提是父亲节点被装进去了。
是更具dp[i][1]=val[i];
在推导的过程中,虽然刚开始容量为m的每个格子不是都有val[i]的值。
但是放入多少个,例如n,那么对于在容量为n的格子里,就一定会有val[i]的存在
*/
相关文章推荐
- HDU 1561 The more, The Better (树形DP,常规)
- HDU 1561 The more, The Better (树形dp)
- HDU 2196-Computer(经典树形DP)
- HDU 3534 Tree(经典树形dp)
- HDU 4616 Game(经典树形dp+最大权值和链)
- hdu 1561 The more, The Better(树形DP入门)
- HDU---1561-The more, The Better (树形DP)
- HDU 1561 The more, The Better 超详细题解(树形DP + 依赖背包)
- HDU - 5834 Magic boy Bi Luo with his excited tree 树形DP(经典)
- hdu 1561 The more, The Better(树形DP入门)
- HDU 1561 The more, The Better 树形DP(0-1背包)
- HDU 1561 The more, The Better (树形DP)
- HDU 1561 The more, The Better - 依赖背包+树形dp基础
- hdu-1561 The more, The Better (树形dp入门,有依赖的背包问题
- HDU 1561 The more, The Better(树形DP入门)
- HDU 1561 The more, The Better 树形DP(0-1背包)
- HDU 1561 The more, The Better(树形DP)
- hdu 1561 The more, The Better 树形dp水题
- hdu 1561 (树形dp)The more, The Better
- HDU 1561 The more, The Better (树形dp)