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