[HDU1561]The more, The Better

题目大意:有n座城堡,每座城堡打掉后能获得一个价值,但某些城堡需要在打掉另一个城堡后才能打,求打掉m座城堡能获得的最大价值。

解题思路:这是一道有依赖的背包问题,可以用树形dp的方式做。

设f[i][j]表示打掉以i为根的子树中的j个城堡所获得的最大价值,则有f[i][j]=max(f[i][j-k]+f[son][k]);(0≤k≤j-1,son是i的子节点)

由于题目给出的是森林,我们把所有树的根节点连到0号节点上,就变成一棵树了。那么m就要相应的加1。最后的答案为f[0][m](m为加1后的)。

时间复杂度$O(nm^2)$。

C++ Code:

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define max(a,b) (((a)>(b))?(a):(b))
int f[205][205],n,m;
vector<int>e[205];
void dfs(int root){
	for(int i=0;i<e[root].size();++i){
		int son=e[root][i];
		dfs(son);
		for(int j=m;j>1;--j)
		for(int k=0;k<j;++k)
		f[root][j]=max(f[root][j],f[root][j-k]+f[son][k]);
	}
}
int main(){
	while(scanf("%d%d",&n,&m)&&n+m){
		++m;
		memset(f,0,sizeof f);
		for(int i=0;i<=201;++i)e[i].clear();
		for(int i=1;i<=n;++i){
			int x,y;
			scanf("%d%d",&x,&y);
			e[x].push_back(i);
			for(int j=1;j<=m;++j)
			f[i][j]=y;
		}
		dfs(0);
		printf("%d
",f[0][m]);
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/Mrsrz/p/7297537.html