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]);
        }
    }
    


  • 相关阅读:
    2019年1月26日训练日记
    2019年1月25日训练日记
    2019年1月24日训练日记
    2019年1月23日训练日记
    2019年1月22日训练日记
    2019年1月21日训练日记
    2019年1月20日训练日记
    2019年1月19日训练日记
    2019年1月18日训练日记
    C语言学习小结
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348105.html
Copyright © 2011-2022 走看看