树形DP 此代码还可以优化

ans[i][j] 代表以i节点的子树 攻j个城堡 的最优值

详解见代码注释

http://acm.hdu.edu.cn/showproblem.php?pid=1561

#include<iostream>
#include<string>
#include<string.h>
#include<queue>
#include<math.h>
#include<algorithm>
#include<vector>
#include<stdio.h>
#define Max 0x7ffffff

using namespace std;

int ans[211][211];
int value[211];//第n 个城堡的价值
struct node
{
    struct tt *next;
}mem[201];//用邻接表储存 树
struct tt
{
    struct tt *next;
    int k;
};
inline void build(int i,int j)//建树
{
    struct tt *t=new tt;
    t->k=j;
    t->next=mem[i].next;
    mem[i].next=t;
}
inline void free(int n)//释放空间
{
    struct tt *t,*w;
    for(int i=0;i<=n;i++)
    {
        t=mem[i].next;
        mem[i].next=NULL;//不能忽略
        while(t!=NULL)
        {
            w=t->next;
            delete(t);
            t=w;
        }
    }
}
int dp(struct tt *&t,int j)
{
    if(t==NULL)//搜到此节点为空时
    {
        if(j==0)//如果还需0个城堡 正好满足 所以 为值0
        return 0;
        return -Max;//否则 返回极小
    }
    int i=t->k;//获取节点数值
    if(ans[i][j]!=-1)//避免重复
    return ans[i][j];
    if(j==0)//攻0个城堡且节点不为空 值为0
    {
        ans[i][j]=0;
        return ans[i][j];
    }
        if(j==1)攻1个城堡两种可能 攻节点本身 或者从兄弟节点中选

        {
            ans[i][j]=max(dp(t->next,j),value[i]);
            return ans[i][j];
        }

        //你猜
        ans[i][j]=dp(t->next,j);//可能本节点不选 完全选从其兄弟节点中选
        for(int l=0;l<j;l++)//选本节点 再从其子结点 和兄弟节点中选择
        {
            ans[i][j]=max(ans[i][j],dp(mem[i].next,l)+dp(t->next,j-1-l)+value[i]);
        }
        if(ans[i][j]>=0)
        return ans[i][j];
        ans[i][j]=min(ans[i][j],-Max);
        return ans[i][j];
}
int main()
{

    int n,m,i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
        break;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&j,&value[i]);
            build(j,i);
        }
        memset(ans,-1,sizeof(ans));
        if(mem[0].next==NULL)
        {
            printf("0\n");
            continue;
        }

        printf("%d\n",max(0,dp(mem[0].next,m)));
        free(n);
    }
    return 0;
}

posted on 2011-12-08 13:04  夜->  阅读(167)  评论(0编辑  收藏  举报