题意:n个洞m个士兵,一棵树,从起点开始往下走,每个节点有一个价值,需要打败该点所有BUGS才能得到他的价值,每个士兵可以打败20个BUGS,一个士兵只能打一个洞,而且你不能走一个节点两遍,问你最多得到的价值。
典型的01背包问题呀,对一个节点来说只是打不打的问题。dfs一下就好了。
思路dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son[i]][k]);
明天再写吧,睡觉QAQ~~
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
vector<int> q[1009];
int n,m;int dp[105][123];
int w[100009],v[1009];
int vis[1009];
int dfs(int u,int f)
{
vis[u]=1;
for(int i=((w[u]+19)/20);i<=m;i++)
{
dp[u][i]=v[u];
}
for(int i=0;i<q[u].size();i++)
{
int v=q[u][i];
if(v==f)continue;
if(vis[v]==0)
dfs(v,u);
for(int j=m;j>=(w[u]+19)/20;j--)
{
for(int k=1;j+k<=m;k++){
dp[u][k+j]=max(dp[u][k+j],dp[u][j]+dp[v][k]);
}
}
}
}
int main()
{
while(cin>>n>>m)
{
if(n==-1&&m==-1) break;
for(int i=0;i<=n;i++) q[i].clear();
for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
for(int i=1;i<n;i++)
{
int x,y;cin>>x>>y;
q[x].push_back(y);
q[y].push_back(x);
}
if(m==0)
{
printf("0\n");continue;
}
memset(vis,0,sizeof vis);
memset(dp,0,sizeof(dp));
dfs(1,1);
cout<<dp[1][m]<<endl;
}
return 0;
}