题目大意:有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; }