这个题是用树形DP的方法做的,所谓树形DP就是在树上做的DP,那么它的状态转移就一定和它的儿子结点有关。
这是一个树形背包问题,我们用f[i][j]表示以i为根的子树在有j个士兵的时候最多能够获得的大脑的数量,那么容易得到状态转移方程是:
f[i][j]=max(f[i][j],f[i][j-k]+f[son[i][p]][k]);
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
bool a[105][105],g[105];
int c[105],v[105],f[105][105];
int n,m;
void dfs(int i)
{
int t=(c[i]+19)/20;
g[i]=1;
for (int j=t;j<=m;j++) f[i][j]=v[i];
for (int j=1;j<=n;j++)
if (a[i][j]) {
if (g[j]) continue;
dfs(j);
for (int k=m;k>=t;k--)
for (int l=1;l<=k-t;l++)
f[i][k]=max(f[i][k],f[i][k-l]+f[j][l]);
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n<0) break;
memset(a,0,sizeof(a));
for (int i=1;i<=n;i++) scanf("%d%d",&c[i],&v[i]);
for (int i=1;i<n;i++)
{
int j,k;
scanf("%d%d",&j,&k);
a[j][k]=1;
a[k][j]=1;
}
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
dfs(1);
printf("%d\n",f[1][m]);
}
return 0;
}

本文介绍了一种解决树形背包问题的树形DP方法,通过定义状态f[i][j]表示以i为根的子树在有j个士兵时最多能获得的大脑数量,并给出状态转移方程f[i][j]=max(f[i][j],f[i][j-k]+f[son[i][p]][k])。此外,文章还提供了完整的C++代码实现。
1199

被折叠的 条评论
为什么被折叠?



