zoukankan      html  css  js  c++  java
  • hdu 1561(树形DP+背包)

    The more, The Better

    Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 6992    Accepted Submission(s): 4100


    Problem Description
    ACboy 很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原 因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
     
    Input
    每 个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。
     
    Output
    对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
     
    Sample Input
    3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0
     
    Sample Output
    5 13
     
    Author
    8600
     
    Source
    分析:dp[u][i]代表以u为根节点的子树取i个结点能够获得的最大收益
    v代表u的子节点,假设在u中取k个结点,那么在v中取i-k个结点,能够获得的最大收益是
    dp[u][i] = max(dp[u][k]+dp[v][i-k],dp[u][i]) 由于孩子依赖父亲,所以父亲必须要选 k>=1
    这个题最重要的一点是给的容量,开始的时候是m,但是由于我们加了一点0点作为根节点进去,而0又是必须要算进去的,所以容量变成了m+1,所以我们统计的是dp[0][m+1]
     
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <algorithm>
    #define N 205
    using namespace std;
    
    int head[N];
    struct Edge{
        int u,v,w,next;
    }edge[N];
    
    int indegree[N];
    void addEdge(int u,int v,int w,int &k){
        edge[k].u = u,edge[k].v = v,edge[k].w=w;
        edge[k].next = head[u],head[u]=k++;
    }
    int n,m;
    int dp[N][N]; ///dp[u][i]代表以u为根节点的子树取i个结点能够获得的最大收益
    ///v代表u的子节点,假设在u中取k个结点,那么在v中取i-k个结点,能够获得的最大收益是
    ///dp[u][i] = max(dp[u][k]+dp[v][i-k],dp[u][i]) 由于孩子依赖父亲,所以父亲必须要选 k>=1
    
    void dfs(int u){
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            dfs(v);
            for(int i=m+1;i>=1;i--){
                for(int k=1;k<i;k++){
                    int t = i-k;
                    dp[u][i] = max(dp[u][k]+dp[v][t],dp[u][i]);
                }
            }
        }
    }
    int main()
    {
    
        while(scanf("%d%d",&n,&m)!=EOF,n+m){
            memset(head,-1,sizeof(head));
            memset(dp,-1,sizeof(dp));
            int tot = 0;
            dp[0][1] = 0;
            for(int i=1;i<=n;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                dp[i][1]=b;
                addEdge(a,i,b,tot);
            }
            dfs(0);
            int ans = dp[0][m+1];
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    LeetCode 189. Rotate Array
    LeetCode 965. Univalued Binary Tree
    LeetCode 111. Minimum Depth of Binary Tree
    LeetCode 104. Maximum Depth of Binary Tree
    Windows下MySQL的安装与配置
    LeetCode 58. Length of Last Word
    LeetCode 41. First Missing Positive
    LeetCode 283. Move Zeroes
    《蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践》读后感
    删除docker下的镜像
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5418485.html
Copyright © 2011-2022 走看看