题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011
思路:dp[i][j]表示以i为根的子树派遣j个士兵占领的最大价值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 111 8 9 10 int dp[MAXN][MAXN]; 11 int num[MAXN],val[MAXN]; 12 int n,m; 13 bool mark[MAXN]; 14 vector<vector<int> >G; 15 16 void dfs(int u) 17 { 18 mark[u]=true; 19 for(int i=num[u];i<=m;i++){ 20 dp[u][i]=val[u]; 21 } 22 for(int i=0;i<G[u].size();i++){ 23 int v=G[u][i]; 24 if(mark[v])continue; 25 dfs(v); 26 for(int i=m;i>=num[u];i--){ 27 for(int j=1;j+i<=m;j++){ 28 if(dp[v][j]){ 29 dp[u][i+j]=max(dp[u][i+j],dp[u][i]+dp[v][j]); 30 } 31 } 32 } 33 } 34 } 35 36 37 int main() 38 { 39 int u,v,ans; 40 while(~scanf("%d%d",&n,&m)){ 41 if(n==-1&&m==-1)break; 42 G.clear(); 43 G.resize(n+2); 44 for(int i=1;i<=n;i++){ 45 scanf("%d%d",&num[i],&val[i]); 46 num[i]=(num[i]+19)/20; 47 } 48 for(int i=1;i<n;i++){ 49 scanf("%d%d",&u,&v); 50 G[u].push_back(v); 51 G[v].push_back(u); 52 } 53 memset(dp,0,sizeof(dp)); 54 memset(mark,false,sizeof(mark)); 55 dfs(1); 56 ans=0; 57 for(int i=1;i<=m;i++){ 58 ans=max(ans,dp[1][i]); 59 } 60 printf("%d ",ans); 61 } 62 return 0; 63 } 64 65 66 67