hdu 4276 The Ghost Blows Light

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

树形dp   比赛时时间不够了没写 

基本思路:

先求是否能到达   如果能到达求每个子树在一定时间下的最优解

ans[i][j] 表示的是 以 i 的父节点为根的子树  还有 j 时间时的最优解

注意的是 到n的路径必须走无需返回 其他的可以走且需要返回

还有一条路所花时间可能是 0 (这里让我wa了N久呀)

代码及其注释:

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <map>

#include <vector>

#include <algorithm>



#define LL long long



using namespace std;



const int N=103;

const int INF=0x5fffffff;

int a[N];//财宝

int ans[N][N*5];//如上所诉

//邻接表

int head[N];

struct node

{

    int j,next;

    int d;

}side[N*2];

int I;

int n;

int limit[N];//为-1 表示没有限制  否则表示是到出口的路径 必须走 而且到 i 的时候时间最少为limit[i]

void build(int i,int j,int d)

{

    side[I].j=j;

    side[I].d=d;

    side[I].next=head[i];

    head[i]=I++;

}

void dfs(int x,int pre)//求出limit 并且去掉多余边

{

    int f=0;

    for(int t=head[x];t!=0;f=t,t=side[t].next)

    {

        int l=side[t].j;

        if(l!=pre)

        {

            dfs(l,x);

            if(limit[l]!=-1)

            limit[x]=limit[l]+side[t].d;

        }else

        {

            if(f==0)

            head[x]=side[t].next;

            else

            side[f].next=side[t].next;

        }

    }

    if(x==n)

    limit[x]=0;

}

int dp(int x,int m)

{

    int l=side[x].j;

    if(ans[l][m]!=-1)//表

    return ans[l][m];

    if(limit[l]!=-1&&side[x].d+limit[l]>m)//此路必走 但时间不够则属于非法的走法 答案负无穷

    {

        ans[l][m]=-INF;return ans[l][m];

    }

    ans[l][m]=0;

    if(l==0)//没有节点

    {return ans[l][m];}

    if(limit[l]==-1)//可以直接到兄弟节点 此节点不走

    ans[l][m]=dp(side[x].next,m);

    if(limit[l]==-1)

    {

        int temp=m-side[x].d*2;//往返

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

        {

            ans[l][m]=max(ans[l][m],a[l]+dp(head[l],i)+dp(side[x].next,temp-i));

        }

    }else

    {

        int temp=m-side[x].d;//无需往返 时间至少为limit[l]

        for(int i=limit[l];i<=temp;++i)

        {

            ans[l][m]=max(ans[l][m],a[l]+dp(head[l],i)+dp(side[x].next,temp-i));

        }

    }

    return ans[l][m];

}

int main()

{

    //freopen("data.txt","r",stdin);

    int m;

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

    {

        memset(head,0,sizeof(head));

        side[0].j=0;

        I=1;

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

        {

            int l,r,d;

            scanf("%d %d %d",&l,&r,&d);

            build(l,r,d);

            build(r,l,d);

        }

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

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

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

        dfs(1,-1);

        if(limit[1]>m)

        {

            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");

            continue;

        }

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

        printf("%d\n", a[1]+dp(head[1],m));//第一个节点无需时间

    }

    return 0;

}

 

你可能感兴趣的:(host)