HDU-1561 The more, The Better (树形DP+分组背包)

题目大意:给出一片森林,总共有n个点,并且都有权值。从中选出m个,使权值和最大。其中,选某个节点之前必须先选其父节点。

题目分析:给所有的树都加一个共同的权值为0的根节点,使森林变成一棵树。定义状态dp(u,k)表示在以节点u为根节点的组中选k个节点的最大权值。则状态转移方程为:

dp(u,k)=max(dp(u,k),dp(v,j)+dp(u,k-j),其中v是u的子节点。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=205;

struct Edge
{
	int to,nxt;
};
Edge e[N<<1];
int n,m,cnt;
int w[N];
int head[N];
int dp[N][N];

void add(int u,int v)
{
	e[cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}

void init()
{
	int fa;
	cnt=w[0]=0;
	memset(head,-1,sizeof(head));
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;++i){
		scanf("%d%d",&fa,w+i);
		add(fa,i);
	}
}

void dfs(int u)
{
	dp[u][1]=w[u];
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].to;
		dfs(v);
		for(int j=m+1;j>=2;--j){
			for(int k=1;k<j;++k)
				dp[u][j]=max(dp[u][j],dp[u][k]+dp[v][j-k]);
		}
	}
}

int solve()
{
	memset(dp,0,sizeof(dp));
	dfs(0);
	return dp[0][m+1];
}

int main()
{
	while(scanf("%d%d",&n,&m)&&(n+m))
	{
		init();
		printf("%d\n",solve());
	}
	return 0;
}

  

时间: 2024-11-05 11:51:54

HDU-1561 The more, The Better (树形DP+分组背包)的相关文章

hdu 1561 The more, The Better(树形dp+01背包)

The more, The Better Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物.但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡.你能帮ACboy算出要获得

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝

HDU ACM 4044 GeoDefense -&gt;树形DP+分组背包

题意:地图是一个编号为1-n的节点的树,节点1是敌方基地,其他叶节点是我方基地.敌人基地会出来敌人,为了防止敌人攻进我方基地,我们可以选择造塔.每个节点只能造一个塔,节点i有ki种塔供选择,价值和攻击力为price_i, power_i,攻击力power_i是让敌人经过这个节点时让敌人的HP减少power_i点.因此从敌人基地到我方任意一个基地的路径,这条路径上所有塔的攻击力之和,就是这个基地的抵抗力. 敌人攻击路径不确定,为了保护我方所有基地,需要确定所有基地中抵抗力最低的一个.我方只有数量为

hdu4003 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4003 Problem Description Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on

[P1273] 有线电视网 (树形DP+分组背包)

题意:给出一棵树,有边权,只有叶子节点有点权,求一个合法方案(选择走到哪几个叶子节点,且路径上的权值和 <= 要走到的叶子节点的点权和),使得选择的叶子节点数量尽量的多: 解法:树形DP+分组背包: 1.树形DP:这是一棵树,所以叫树形DP: 2.分组背包:在这里主要是运用到了它的思想:我们可以设 f[i][j],表示 i节点选择了 j个叶子节点的费用最大值:假设现在在 x节点,它的下面有 n个叶子节点(不是它的儿子),那么我们就要处理出它选 1,2,3,……,n 个叶子节点的情况,但是由于这是

hdu 1561 树形dp+分组背包

题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值. 状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)                    dp[v][j] = m

hdu4044 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4044 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of tower defense games is to try to stop enemies from reaching your bases by building towers which shoot at them

POJ 2486 Apple Tree 树形DP+分组背包

链接:http://poj.org/problem?id=2486 题意:一棵(苹果)树,树上有N个结点(N<=100),起点是结点1.每个结点上有若干个苹果,我可以进行K步操作(K<=200),每次操作是从当前结点移动到相邻的结点,并且到了相邻的结点以后会吃掉上面的所有苹果并且苹果不再长出来,相邻是指两个结点之间有边相连.问在K步操作之后最多可以吃掉多少个苹果. 思路:刚入手的时候觉得是一般的树形背包问题,dp[i][j]代表的是以i为根的子树中走j个结点所能吃到的苹果数,来进行状态转移,但

【P2015】二叉苹果树 (树形DP分组背包)

题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100). N表示树的结点数,Q表示要保留的树枝数量.接下来N-1行描述树枝的信息. 每行3个整数,前两个是它连接的结点的编号.第3个数是

HDU-1011 Starship Troopers (树形DP+分组背包)

题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=105; const