POJ-2486 Apple Tree (树形DP)

题目大意:一棵点带权有根树,根节点为1。从根节点出发,走k步,求能收集的最大权值和。

题目分析:从一个点向其某棵子树出发有三种可能的情况:

1、停留在那棵子树上;

2、再回到这个点;

3、经过这个点走向了其他分支;

定义状态dp(u,k,0/1)表示在u节点为根的子树上走k步并且不回/回到u的最大权值和。则状态转移方程为:

dp(u,k,0)=max(dp(son,j-2,1)+dp(u,k-j,0),dp(u,k-j,1)+dp(son,j-1,0))

dp(u,k,1)=max(dp(son,j-2,1)+dp(u,j-k,1))

代码如下:

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

const int N=105;

int n,m;
int w[N];
int dp[N][N<<1][2];
vector<int>e[N];

void init()
{
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;++i){
		e[i].clear();
		scanf("%d",w+i);
		for(int j=0;j<=m;++j)
			dp[i][j][0]=dp[i][j][1]=w[i];
	}
	int a,b;
	for(int i=1;i<n;++i){
		scanf("%d%d",&a,&b);
		e[a].push_back(b);
		e[b].push_back(a);
	}
}

void dfs(int u,int fa)
{
	for(int i=0;i<e[u].size();++i){
		int v=e[u][i];
		if(v==fa) continue;
		dfs(v,u);
		for(int j=m;j>=1;--j){
			for(int k=1;k<=j;++k){
				dp[u][j][0]=max(dp[u][j][0],dp[v][k-1][0]+dp[u][j-k][1]);
				if(k>=2){
					dp[u][j][0]=max(dp[u][j][0],dp[v][k-2][1]+dp[u][j-k][0]);
					dp[u][j][1]=max(dp[u][j][1],dp[v][k-2][1]+dp[u][j-k][1]);
				}
			}
		}
	}
}

void solve()
{
	dfs(1,-1);
	printf("%d\n",max(dp[1][m][0],dp[1][m][1]));
}

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

  

时间: 2024-10-08 02:25:48

POJ-2486 Apple Tree (树形DP)的相关文章

POJ 2486 Apple Tree (树形dp 经典题)

Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7784   Accepted: 2603 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amoun

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

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

POJ 2486 Apple Tree (树形dp)

这是一个树上的背包转移.注意要用dp[i][j][k]表示第i个节点用了j的路程是否回到i节点,k=0表示回到i点,k=1表示不回到i点.那么实际上就是树上的一个背包转移. #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <string> #include <cctype> #include

URAL_1018 Binary Apple Tree 树形DP+背包

这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过程中,有点难表示转移 后来看了下大神的做法才知道其实可以用背包来模拟 树枝的去留,其实真的是个背包诶,每个子树枝就相当于物品,他占用了多少树枝量,带来多少的收益,就是用背包嘛,于是用树形DP+背包就可以做了 #include <iostream> #include <cstdio> #

[Poj 2486] Apple Tree 树形DP

Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9069 Accepted: 3016 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of

【POJ 2486】 Apple Tree (树形DP)

Apple Tree Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apple

POJ 2486 Apple Tree (树形DP,树形背包)

题意:给定一棵树图,一个人从点s出发,只能走K步,每个点都有一定数量的苹果,要求收集尽量多的苹果,输出最多苹果数. 思路: 既然是树,而且有限制k步,那么树形DP正好. 考虑1个点的情况:(1)可能在本子树结束第k步(2)可能经过了j步之后,又回到本节点(第k步不在本子树) 第二种比较简单,背包一下,就是枚举给本节点的孩子t多少步,收集到最多苹果数.第一种的话要求第k步终止于本节点下的某个子树中,那么只能在1个孩子子树中,所以应该是[其他孩子全部得走回来]+[本孩子不要求走回来]   or  

URAL 1018 Binary Apple Tree 树形DP 好题 经典

1018. Binary Apple Tree Time limit: 1.0 secondMemory limit: 64 MB Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enu

POJ 2486 Apple Tree

很好也很烦的一个树形DP,昨天搞了一晚上是在想不出,后来没办法去看题解了,完事发现非常令人感动的是,我一开始设的状态都错了,然后就一直错了下去,还好及时的回头是岸了. 不说废话了,正题: 题目大意:给一棵树,n个节点,每个节点有一个权值,要求从节点1出发最多走k步,求所经过的点的权值和的最大值,每个点经过一次后就变为0: 最近做了一些树DP 也小小的总结了点规律,树形dp一般是设dp[rt][j]即以rt为根的子树j状态.这个题可以设 dp[rt][j][0]表示以rt为根的子树走j步最后不回到

POJ 2486 Apple Tree ( 树型DP )

#include <iostream> #include <cstring> #include <deque> using namespace std; #define SIZE 230 #define BACK 1 #define AWAY 0 int DP[SIZE][SIZE][2]; bool visits[SIZE]; int vals[SIZE]; deque< int > tree[SIZE]; int num, steps; void dfs