树形动态规划

我颓了


今天复习一下树形DP

eg1.没有上司的舞会

一道简单的入门树形DP
代码如下


#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
const int maxn=10007;
int dp[maxn][2];
bool f[maxn][2];
int v[maxn];
int cnt[maxn];
int son[maxn][maxn];
int fa[maxn];
int work(int a,int b) //记忆化搜索 
{
	if(f[a][b]){
		return dp[a][b];
	} 
	f[a][b]=true;
	int sum=0;
	if(b==1){  //取这个点 
		for(int i=1;i<=cnt[a];i++){
			int u=son[a][i];
			sum+=work(u,0); //不能取这个节点的儿子(下司) 
		}
		dp[a][b]=v[a]+sum;  //这个点的最优利益就是所有它的下司都不去的最大利益之和与它本身快乐值的利益之和 
	}
	else{
		for(int i=1;i<=cnt[a];i++){
			int u=son[a][i];
			sum+=max(work(u,0),work(u,1));  //下司可去可不去,在去与不去中取最大值 
		}
		dp[a][b]=sum;  //这个点的最优利益就是所有它的下司去与不去的最大利益之和
	}
	return dp[a][b];
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>v[i];
	}
	for(int i=1;i<=n;i++){
		int k,l;
		cin>>l>>k;
		son[k][++cnt[k]]=l;
		fa[l]++;
	}
	int s;
	for(int i=1;i<=n;i++){
		if(!fa[i]){
			s=i;   //找到最大的上司,作为根节点开始搜索 
		}
	}
	int ans=max(work(s,0),work(s,1)); //在取根节点与不取根节点中取最大值 
	cout<<ans;
} 

总结:树形动态规划就是在树上做的动态规划,例题一就是一道基本的树形动态规划题目,主要注意画图分析


eg2.垃圾陷阱

原文地址:https://www.cnblogs.com/XJack/p/10884065.html