poj 2486 Apple Tree

http://poj.org/problem?id=2486

树形DP 我一般都是先用邻接表保存树 然后用的都是子树和所有兄弟树的dp方法

自己感觉理解也行呀 但是没见有多少人用呢,也许自己有点另类

老是出错 思维能力还是不够 越来越感觉acm是在练一个人的思维了

题目大意:

给一个树 节点有一定数目的苹果

人在1(根点)最多走K步 问最多可以得到多少苹果

思路:

ans[i][j][0] 表示包括i在内所以其子节点和右边兄弟树 可以走j步 可以存在不回来的情况 的最佳答案

ans[i][j]][1] 这个必须都回来

代码及其注释:

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<queue>

#include<cmath>

#include<stack>

#include<algorithm>

#define LL long long



using namespace std;



const int N=105;

const int MIN=-100000000;

struct node

{

    struct tt *next;

}mem[N];

struct tt

{

    int j;

    struct tt *next;

};

bool had[N];

bool link[N][N];

int applenum[N];

int ans[N][N*2][2];

int a[3][3][3];

void build(int i,int j)

{

    struct tt *t=new tt;

    t->j=j;

    t->next=mem[i].next;

    mem[i].next=t;

}

void Dele(int n)

{

    struct tt *t;

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

    {//cout<<i<<endl;

        while(mem[i].next!=NULL)

        {//cout<<"iii"<<endl;

            t=mem[i].next;

            mem[i].next=t->next;

            delete t;

        }

    }

}

int dp(struct tt *t,int k,int back)

{

   if(t==NULL)//各种 无法走的情况

   return 0;

   if(k<0)

   return 0;

   if(back==1&&k<1)

   return 0;

   if(ans[t->j][k][back]!=-1)

   return ans[t->j][k][back];

   int itemp=0;

   int w=0;

   for(int i=0;i<=k;++i)

   {

       if(i>=1)

       w=applenum[t->j];//要回去时 只有可以回去 才能加上本节点的苹果树

       itemp=max(itemp,w+dp(mem[t->j].next,i-2,1)+dp(t->next,k-i-1,back));//给子树一部分 往兄弟传一部分 注意路径需要的步数减去

       if(back==0)

       {

           w=applenum[t->j];//这是子树不用回来的 其他差不多

           itemp=max(itemp,w+dp(mem[t->j].next,i-1,0)+dp(t->next,k-i-1,1));

       }

   }

   ans[t->j][k][back]=itemp;

   if(t->next!=NULL)

   ans[t->j][k][back]=max(ans[t->j][k][back],dp(t->next,k,back));//如果不走此节点

   return  ans[t->j][k][back];

}

void dfs(int x,int n)

{

    had[x]=true;

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

    {

        if(link[x][i]&&!had[i])

        {

            build(x,i);//建立单向树

            dfs(i,n);

        }

    }

}

int main()

{

    int n,k;

    while(scanf("%d %d",&n,&k)!=EOF)

    {

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

        {

            scanf("%d",&applenum[i]);

        }

        memset(link,false,sizeof(link));

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

        {

            int x,y;

            scanf("%d %d",&x,&y);

            link[x][y]=link[y][x]=true;

        }

        if(n==1)

        {

            printf("%d\n",applenum[1]);

            continue;

        }

        memset(had,false,sizeof(had));

        dfs(1,n);

        memset(ans,-1,sizeof(ans));

        printf("%d\n",applenum[1]+dp(mem[1].next,k-1,0));

        Dele(n);

    }

}

  

 

你可能感兴趣的:(apple)