剑指offer:C++树形DP基础——二叉苹果树

问题 G(1375): 【基础算法】二叉苹果树

时间限制: 1 Sec  内存限制: 64 MB

题目描述

有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点)。这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是 1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有 4 个树枝的树:  现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。

输入

第1行: 2个空格分开的整数,N 和 Q(1≤Q≤N,1<N≤100),N表示树的结点数,Q表示要保留的树枝数量。 接下来 N-1 行描述树枝的信息。 每行3 个整数,前两个是它连接的结点的编号。第3 个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过30000 个。

输出

第1行:一个整数,表示最多能留住的苹果的数量。

样例输入

5 2 
1 3 1 
1 4 10 
2 3 20 
3 5 20 

样例输出

21

一道比较基础的树形DP的题。

f_{i,j}表示以i为根节点的子树中,选了j条边,获得了f_{i,j}个苹果的最大值。

按照以前的经验,我们可以得出状态转移方程:

f_{i,j}=max(f_{i,j},f_{v,k}+f_{i,j-k}+w_{i,j})(k表示i的儿子节点v选了k条边

交上去,发现错了!?

原来此题于往常的题的区别在于苹果(权值)是在边上而不是在点上,所以我们需要修改一下状态转移方程:

f_{i,j}=max(f_{i,j},f_{v,k}+f_{i,j-k-1}+w_{i,j})

#include 
#include 
#include 
#include 
using namespace std;

const int N=110;
#define max(a,b) a>=b?a:b

struct node {
	int v,w;
	node() {};
	node(int V,int W) { v=V;w=W; };
};

int f[N][N],n,m;
vector  G[N];

int dfs(int u,int fa) {
	int val=1;
	for(int i=0,v,w;i=0;j--)
			for(int k=0;k>n>>m;
	for(int i=1,u,v,w;i>u>>v>>w;
		G[u].push_back( node(v,w) );
		G[v].push_back( node(u,w) );
	}
	dfs(1,0);
	cout<

 

你可能感兴趣的:(C++,动态规划,树形DP,C++,动态规划,二叉苹果树,树形DP)