HDOJ 1011 Starship Troopers(树DP)

题意描述很纠结,前后WA了数十次……

AC后的理解:给一棵树,每个结点有2个值,bug和brain,要获取brain必先消灭bug,现从结点1出发,给你m个starship troopers,每个starship troopers能对付20个bug,问最多能得到多少brain。在攻克的过程中,对于途中经过的结点,如果该点bug不为0,则要留下一个starship troopers在此结点,否则不需留。对于叶子结点,即使bug为0,也要派starship troopers去收获brain。

data:

5 0
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
5 2
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
-1 -1

answer:0 9

View Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 110
int n,m,e;
int bug[N],brain[N];
int first[N],next[N<<1],v[N<<1];
int dp[N][N];
void init()
{
    e=0;
    memset(first,-1,sizeof(first));
}
void add(int a,int b)
{
    v[e]=b;
    next[e]=first[a];
    first[a]=e++;
}
void dfs(int a,int fa)
{
    dp[a][0]=0;
    for(int j=1;j<=m;j++)
    {
        dp[a][j]= j>=bug[a] ? brain[a] : 0;
    }
    int i,b;
    bool f=1;
    for(i=first[a];~i;i=next[i])
    {
        b=v[i];
        if(b==fa)   continue;
        if(f)
        {
            if(bug[a]==0)   dp[a][0]=brain[a];
            f=0;
        }
        dfs(b,a);
        for(int j=m;j;j--)
        {
            for(int k=1;j-k>=bug[a];k++)
            {
                dp[a][j]=max(dp[a][j],dp[a][j-k]+dp[b][k]);
            }
        }
    }
}
int main()
{
    int a,b;
    while(scanf("%d%d",&n,&m))
    {
        if(n==-1 && m==-1)  break;
        init();
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&bug[i],&brain[i]);
            bug[i]=(bug[i]+19)/20;
        }
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        if(m==0)
        {
            puts("0");  continue;
        }
        dfs(1,0);
        int ans=dp[1][m];
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2012-10-10 10:01  BeatLJ  阅读(426)  评论(0编辑  收藏  举报