题意:
有n个房间组成一棵树,你有m个士兵,从1号房间开始让士兵向相邻的房间出发,每个房间里有一个brain,每一个士兵可以消灭20个bugs,求可以获得的最大brain
分析:
树形01背包,树用邻接表存储,深度优先遍历该树~dp[i][j]表示在i结点,放j个人所获得的最大值
//AC CODE:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
using namespace std;
const int maxn=220;
struct Node
{
int number,p;
} node[maxn];
int n,m;
bool vis[maxn];
int dp[maxn][maxn];//dp[i][j]表示在i结点,放j个人所获得的最大值
int adj[maxn][maxn];//邻接表
void dfs(int k)
{
vis[k]=true;
int num=(node[k].number+19)/20;
for(int i=num; i<=m; i++)
dp[k][i]=node[k].p;
for(int i=1; i<=adj[k][0]; i++)
{
int u=adj[k][i];
if (vis[u])//别忘了剪枝
continue;//
dfs(u);
//关键部分 01 package
for(int j=m; j>=num; j--)
for(int l=1; l+j<=m; l++)
dp[k][j+l]=max(dp[k][j+l],dp[k][j]+dp[u][l]);
}
}
int main()
{
while(scanf("%d%d",&n,&m)&&(n!=-1&&m!=-1))
{
memset(vis,false,sizeof(vis));
memset(dp,0,sizeof(dp));
memset(adj,0,sizeof(adj));
for(int i=1; i<=n; i++)
scanf("%d%d",&node[i].number,&node[i].p);
int b,e;
for(int i=1; i<n; i++)//用邻接表存树
{
scanf("%d%d",&b,&e);
adj[b][0]++;
adj[b][adj[b][0]]=e;
adj[e][0]++;
adj[e][adj[e][0]]=b;
}
if(m==0)
printf("0\n");
else
{
dfs(1);
printf("%d\n",dp[1][m]);
}
}
}