树型dp Zoj3201 tree of tree


 
^_^ o(∩∩)o...我去刚要打个哈哈出现这么多颜文字还那么丑


这题 算是 树型dp经典的 小变种 了吧 。。

首先 理解一下 啥叫 树型dp,
树型树型,告诉我们 这是一个 基于树(二叉树)结构的dp

那么自然要有建树的过程。
建树 有 三种  1)单方向 2)邻接表  3)孩子兄弟

再想到dp是自下ershang
故而先计算孩子节点信息
利用孩子节点信息算出根节点信息

写出状态转移方程

通常分为 叶子节点:dp[][]
                非叶子节点: dp[i][]= blablabla


这道题的状态转移方程

考虑每个节点 i为根 的sizeK的子树的最大 weight;
    dp[i][sizeK]=max(dp[i][sizeK] , dp[i的孩子][sizeK-k]+dp[i][k]);  (  sizeK= K ~ 1, k=sizeK~1);

最后  扫一遍 dp[i][题目指定子树大小];

ok.

#include <iostream>
#include <string.h>
#include <vector>
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;

const int maxn=110;
int f[maxn][maxn],N,K,w[maxn];
bool vis[maxn];
vector<int> node[maxn];


void dfs(int r)
{
	int size=node[r].size(),i,j,t;
	f[r][0]=0;
	f[r][1]=w[r];
	for(i = 0;i < size; i++)
	{
		j=node[r][i];
		dfs(j);
		for(j = K;j >= 1; j--)
		{
			for (t = j; t>=1; t--) {
				f[r][j]=Max(f[r][j],f[r][t]+f[j][j-t]);
			}

		}
			
	}

}

int main(void)
{
	while(cin>>N>>K)
	{
		int i;
		for (i = 0; i < N ; i++) {
			cin>>w[i];
			node[i].clear();
		}
		int a,b;
		memset(vis,0,sizeof(vis));
		memset(w,0,sizeof(w));
		for (i = 1; i < N; i++) {
			cin>>a>>b;
			node[a].push_back(b);
			vis[b]=true;
		}
		for(i = 0;i < N && vis[i] ;i++);
		dfs(i);
		int ans=0;
		for (i = 0; i < N; i++) {
			if(f[i][K]>ans) ans=f[i][K];
		}
		cout<<ans<<endl;
	}
	return 0;
}


你可能感兴趣的:(树型dp)