zoukankan      html  css  js  c++  java
  • 树形DP(01组合背包The Ghost Blows Light HDU4276)

    题意:有n个房间,之间用n-1条道路连接,每个房间都有一个定时炸弹,在T时间后会一起爆炸,第i个房间有pi价值的珠宝,经过每条道路都需要花费一定的时间,一个人从1房间开始 ,从n房间出去,保证再不炸死的情况下可以带走的最大价值的珠宝是多少?

    分析:很容易想到,这是树上的01背包,可以抽象的想,要是珠宝价值最大即满足:1到n的路径必须经过,且经过一次,而与该路径相连的副路径要么走0次要么走2次 (因为还有回来),所以用DP[i][j]表示以i为根节点的子树,花费j的时间可以获得的最大价值,需要特殊处理的是1-n经过的路径时间花费全部设为0,然后以1为根节点dfs,最后DP[1][T-ans]+value[1]就是最大值,下面是动态方程:

    for(int j=cost;j>=edge[i].w*2;j--)
    {
         for(int k=0;k<=j-edge[i].w*2;k++)
               dp[u][j]=max(dp[u][j],dp[u][j-edge[i].w*2-k]+value[v]+dp[v][k]);//u为子树是经过j时间获得的最大价值
    }
    程序:
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include"stdio.h"
    #include"string.h"
    #include"stdlib.h"
    #include"queue"
    #include"algorithm"
    #include"string.h"
    #include"string"
    #include"math.h"
    #include"vector"
    #include"stack"
    #include"map"
    #define eps 1e-4
    #define inf 0x3f3f3f3f
    #define M 209
    #define PI acos(-1.0)
    using namespace std;
    struct node
    {
        int u,v,w,next;
    }edge[M*2];
    int t,head[M],fa[M],pre[M],dp[M][555],value[M];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].w=w;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void dfs(int u,int f)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==f)continue;
            fa[v]=u;
            pre[v]=i;
            dfs(v,u);
        }
    }
    void dfs1(int u,int f,int cost)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==f||cost-edge[i].w*2<0)continue;
            dfs1(v,u,cost-edge[i].w*2);
            for(int j=cost;j>=edge[i].w*2;j--)
            {
                for(int k=0;k<=j-edge[i].w*2;k++)
                    dp[u][j]=max(dp[u][j],dp[u][j-edge[i].w*2-k]+value[v]+dp[v][k]);
            }
        }
    }
    int main()
    {
        int n,T,i,u;
        while(scanf("%d%d",&n,&T)!=-1)
        {
            init();
            for(i=1;i<n;i++)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            for(i=1;i<=n;i++)
            scanf("%d",&value[i]);
            fa[1]=-1;
            dfs(1,1);
            int ans=0;
            for(u=n;u!=1;u=fa[u])
            {
                ans+=edge[pre[u]].w;
                edge[pre[u]].w=edge[pre[u]^1].w=0;
            }
            T-=ans;
            if(T<0)
            {
                printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!
    ");
                continue;
            }
            memset(dp,0,sizeof(dp));
            dfs1(1,1,T);
            printf("%d
    ",dp[1][T]+value[1]);
        }
    }
    


  • 相关阅读:
    笔记35 跨重定向请求传递数
    判断邮箱的正则表达式
    按钮
    async await 的用法
    笔记34 Spring MVC的高级技术——处理multipart形式的数据
    Convert Sorted Array to Binary Search Tree
    Binary Tree Zigzag Level Order Traversal
    Unique Binary Search Trees,Unique Binary Search Trees II
    Validate Binary Search Tree
    Populating Next Right Pointers in Each Node,Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348105.html
Copyright © 2011-2022 走看看