zoukankan      html  css  js  c++  java
  • HDU 1561 The more, The Better (树形DP)

    The more, The Better

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


    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
     
    Recommend
    LL
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int VM=210;
    
    struct Edge{
        int to,nxt;
    }edge[VM<<1];
    
    int n,m,cnt,head[VM];
    int vis[VM],val[VM],dp[VM][VM]; //dp[i][j]表示在以i为根的子树上,攻克j个结点获得的最大价值
    
    void addedge(int cu,int cv){
        edge[cnt].to=cv;
        edge[cnt].nxt=head[cu];
        head[cu]=cnt++;
    }
    
    void DFS(int u){
        if(vis[u])
            return ;
        vis[u]=1;
        dp[u][1]=val[u];    //选一个肯定选自己这个结点
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to;
            if(!vis[v]){
                DFS(v);
                for(int j=m;j>=1;j--)
                    for(int k=1;k<j;k++)    //下面这个循环必须是k<j结束,不能取等号,因为至少需要留一个点来取u点
                        dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
            }
        }
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d",&n,&m)){
            if(n==0 && m==0)
                break;
            cnt=0;
            memset(head,-1,sizeof(head));
            int u,v;
            for(v=1;v<=n;v++){
                scanf("%d%d",&u,&val[v]);
                addedge(u,v);
                //addedge(v,u);
            }
            memset(vis,0,sizeof(vis));
            memset(dp,0,sizeof(dp));
            m++;    //虚拟构造了结点0
            DFS(0);
            printf("%d\n",dp[0][m]);
        }
        return 0;
    }
  • 相关阅读:
    5.19 省选模拟赛 T1 小B的棋盘 双指针 性质
    5.15 省选模拟赛 容斥 生成函数 dp
    5.15 省选模拟赛 T1 点分治 FFT
    5.15 牛客挑战赛40 B 小V的序列 关于随机均摊分析 二进制
    luogu P4929 【模板】舞蹈链 DLX
    CF 878E Numbers on the blackboard 并查集 离线 贪心
    5.10 省选模拟赛 拍卖 博弈 dp
    5.12 省选模拟赛 T2 贪心 dp 搜索 差分
    5.10 省选模拟赛 tree 树形dp 逆元
    luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
  • 原文地址:https://www.cnblogs.com/jackge/p/3090493.html
Copyright © 2011-2022 走看看