• 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;
    }
    
  • 相关阅读:
    Scrapy爬虫框架
    python Re库的介绍
    正则表达式,regular expression, regex, RE
    信息标记的三种形式
    python Beautiful Soup库入门
    python requests第三方库详解
    递归算法
    枚举算法
    MySQL CONCAT()与GROUP_CONCAT()的使用
    关于日期函数查询总结
  • 原文地址:https://www.cnblogs.com/liulangye/p/2680672.html
Copyright © 2020-2023  润新知