POJ 2486 Apple Tree(树DP)

题意:现有一棵苹果树,树中每个结点上都有一定数量的苹果,问若从根结点出发,最多只能走K步(每一步都只能从一个结点走到相邻结点),最多能摘多少苹果。

分析:定义dp[i][j][0],表示从 i 出发,向下走 j 步,最后回到 i 最多能摘的苹果数,dp[i][j][1]表示从 i 出发,向下走 j 步最后没有回到 i 最多能摘多少苹果。

View Code
#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;

#define N 101

int n,e,step,w[N];

int first[N],next[N<<1],v[N<<1];

int dp[N][N<<1][2];

void init()

{

    e=0;

    memset(first+1,-1,sizeof(first[0])*n);

}

void add(int a,int b)

{

    v[e]=b;

    next[e]=first[a];

    first[a]=e++;

}

void dfs(int a,int fa)

{

    memset(dp[a],0,sizeof(dp[0]));

    dp[a][0][0]=w[a];

    int i,b;

    for(i=first[a]; ~i; i=next[i])

    {

        b=v[i];

        if(b==fa)   continue;

        dfs(b,a);

        for(int j=step; j>=0; j--)

        {

            for(int k=0; j+k+2<=step; k+=2)

            {

                dp[a][j+k+2][1]=max(dp[a][j+k+2][1],dp[a][j][1]+dp[b][k][0]);

            }

            if(~j&1)

            {

                for(int k=0; j+k+2<=step; k+=2)

                {

                    dp[a][j+k+2][0]=max(dp[a][j+k+2][0],dp[a][j][0]+dp[b][k][0]);

                }

                for(int k=0; j+k+1<=step; k++)

                {

                    dp[a][j+k+1][1]=max(dp[a][j+k+1][1],dp[a][j][0]+max(dp[b][k][1],dp[b][k][0]));

                }

            }

        }

    }

}

int main()

{

    int a,b;

    while(~scanf("%d%d",&n,&step))

    {

        init();

        for(int i=1; i<=n; i++)   scanf("%d",&w[i]);

        for(int i=1; i<n; i++)

        {

            scanf("%d%d",&a,&b);

            add(a,b);

            add(b,a);

        }

        dfs(1,0);

        int ans=0;

        for(int j=0; j<=step; j++)    ans=max(ans,max(dp[1][j][0],dp[1][j][1]));

        printf("%d\n",ans);

    }

    return 0;

}

你可能感兴趣的:(apple)