• 有依赖的背包问题(树状dp 深搜)


    有 N 个物品和一个容量是 V 的背包。

    物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。

    如下图所示:

    如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。

    每件物品的编号是 i,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N。

    求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。

    输出最大价值。

    输入格式
    第一行有两个整数 N,V,用空格隔开,分别表示物品个数和背包容量。

    接下来有 N 行数据,每行数据表示一个物品。
    第 i 行有三个整数 vi,wi,pi,用空格隔开,分别表示物品的体积、价值和依赖的物品编号。
    如果 pi=−1,表示根节点。 数据保证所有物品构成一棵树。

    输出格式
    输出一个整数,表示最大价值。

    数据范围
    1≤N,V≤100
    1≤vi,wi≤100
    父节点编号范围:

    内部结点:1≤pi≤N;
    根节点 pi=−1;
    输入样例
    5 7
    2 3 -1
    2 2 1
    3 5 1
    4 7 2
    3 6 2
    输出样例:
    11

    思路:
    题意就是选某一个点 然后这个点的 所有依赖节点都要存放进去 然后 在不超过背包容积的情况下得到值的最大;
    分析:顺序遍历 以某一个点作为根节点向下遍历出来 去掉这个根节点的容量(因为每一次我们必须要选择这个点) ,看所有儿子节点选或者不选的情况 然后儿子节点也可能还有儿子节点 就是一个递归处理
    每一次去掉根节点后剩下的背包容量分给儿子节点 (这里就是一个分组背包 )看一看如何分配能取到最大值
    最后把根节点的价值加上 如果小于根节点的容积 那么就是0 取不了这个物品

    
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 110;
    int dp[N][N],w[N],v[N];
    int n , m;
    int idx, h[N],ne[N],e[N];
    void add(int a, int b)
    {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
    
    void dfs(int u)
    {
       for(int i = h[u] ; ~i ; i = ne[i])
       {
           
           int son = e[i];
           dfs(e[i]);
           
           //分组背包
           for(int j = m - v[u] ; j >= 0 ; j --)//去掉根节点的容积遍历 如何分配
           {
               for(int k = 0 ; k <= j ; k++)//分给儿子的容积k能大到多少决策 dp[u][j-k] 就是能分配给根节点的容积是多少
               {
                   dp[u][j] = max(dp[u][j] , dp[u][j-k] + dp[son][k]);//
               }
           }
           
       }
       
       for(int i = m ; i >= v[u] ; i --) dp[u][i] = dp[u][i-v[u]] + w[u];
       
       for(int i = 0 ; i < v[u];i++) dp[u][i] = 0; 
       
    }
    int main()
    {
        cin >> n >> m ;
        memset(h,-1,sizeof h);
          int root;
        for(int i =1 ; i <= n ; i++)
        {
              int p;
            cin >> v[i] >>w[i] >> p ;
            if(p == -1)root = i;
            else add(p,i);
        }
        
          dfs(root);
        cout << dp[root][m] << endl;
        return 0 ;
    }
    
  • 相关阅读:
    Hello,world的几种写法!
    浮动与清除浮动
    css中表格的table-layout属性特殊用法
    CSS之照片集效果
    CSS之transition过渡练习
    CSS之过渡简单应用—日落西山
    CSS之立方体绘画步骤
    CSS之立体球体
    transform
    Vue.sync修饰符与this.$emit('update:xxx', newXXX)
  • 原文地址:https://www.cnblogs.com/wk-love-zsy/p/13899958.html
Copyright © 2020-2023  润新知