zoukankan      html  css  js  c++  java
  • hdoj1010Starship Troopers (树dp,依赖背包)

    称号:hdoj1010Starship Troopers 


    题意:有一个军队n个人要占据m个城市,每一个城市有cap的驻扎兵力和val的珠宝,并且这m个城市的占率先后具有依赖关系,军队的每一个人能够打败20个城市的防守者,并且占据城市后能够得到城市的珠宝。问最多能够得到多少珠宝?


    分类:树形dp入门题。依赖背包


    分析:是hdoj1561题目的复杂版。相同我们要构建一颗dp树,从叶子到根往上dp。


    定义状态:dp【i】【j】 以节点 i  为根节点的子树。花费 j 的兵力能够得到的最大珠宝数。

    状态转移方程:dp【father】【j】 = Max(dp【father】【j】,dp【father】【k】+dp【child】【j-k】)

    注意:1:在一个节点即使仅仅有没有兵力,也至少花费1的兵力攻占。

        2:注意初始化


    代码:

    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <algorithm>
    #include <vector>
    #define Del(a,b) memset(a,b,sizeof(a))
    const int N = 150;
    using namespace std;
    int n,m;
    int dp[N][N],vis[N];  //dp[i][j]表示在节点i,从以i为根节点的子树下选择j个城市的最大价值
    int cap[N],val[N];
    vector<int> v[N];
    
    void creat(int o)
    {
        vis[o]=1;
        int tmp=(cap[o]+19)/20;
        if(tmp>m)
            return ;
        for(int i=tmp; i<=m; i++)
            dp[o][i]=val[o];
        for(int i=0; i<v[o].size(); i++)
        {
            int t=v[o][i];
            if(vis[t]==1)
                continue;
            if(v[t].size()>0)
            {
                creat(t);
                for(int j = m ; j > tmp ; j--)   //j>1表示此节点一定要取 0-1背包
                {
                    for(int k=0; k<=j-tmp; k++) //枚举给当前节点的其它子树留多少可选择的城市
                        dp[o][j]=max(dp[o][j],dp[o][j-k]+dp[t][k]);
                }
            }
        }
        if(dp[o][0]>0)//以u为根节点的子树至少要有一个人才干够获得该节点的brain
        {
            dp[o][1]=max(dp[o][1],dp[o][0]);
            dp[o][0]=0;
        }
    }
    
    int main()
    {
        while(cin >> n >> m )
        {
            if(n==-1 && m==-1)
                break;
            Del(dp,0);
            Del(vis,0);
            for(int i=1; i<=n; i++)
                scanf("%d%d",&cap[i],&val[i]);
            for(int i=1; i<n; i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
            }
            creat(1);
            for(int i = 0 ; i <= n ; i ++)
                v[i].clear();
            cout << dp[1][m] << endl;
        }
        return 0;
    }
    


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    关于ueditor1.4.3版复制section标签丢失class和style样式问题
    关于移动手机端富文本编辑器qeditor图片上传改造
    移动web HTML5使用photoswipe模仿微信朋友圈图片放大浏览
    PLSQL Developer如何设置自动打开上次编辑的文件
    Linux目录结构
    git与代码托管工具
    mysql的索引
    Gson学习记录
    java线程池的初探
    netty学习总结(一)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4717541.html
Copyright © 2011-2022 走看看