• AcWing 10. 有依赖的背包问题


    题目链接

    https://www.acwing.com/problem/content/10/

    题解

    需要注意的点就是,f[u][j]实际上是优化过第第二维后的状态表示,原状态表示应该是f[u][i][j]:对于根结点u,考虑其前i个子树,总体积不超过j的最大价值
    dfs(root)的递归含义是:以root为根,考虑其所有子树,总体积不超过max_V的最大价值。

    AC代码

    import java.util.*;
    
    public class Main {
        static int N = 110;
        static int[] v = new int[N], w = new int[N];
        static int[] h = new int[N], e = new int[N], ne = new int[N];
        static int[][] f = new int[N][N];
        static int idx = 0;
        static int n, m;
        
        static {
            Arrays.fill(h, -1);
        }
        
        static void add(int a, int b) {
            e[idx] = b;
            ne[idx] = h[a];
            h[a] = idx ++;
        }
        
        static void dfs(int u) {
            for (int j = v[u]; j <= m; j ++) f[u][j] = w[u];
            
            // 优化了第二维,省略了i,对于实际上应该:是对于根结点u
            // 考虑其前i个子树,总体积不超过j的最大价值
            for (int i = h[u]; i != -1; i = ne[i]) { 
                int son = e[i];
                dfs(son);
                for (int j = m; j >= v[u]; j --) // 所以这里要倒写
                    // 考虑前i个子树,给son_i这个子树,k体积,其他j - k体积
                    for (int k = 0; k <= j - v[u]; k ++) {
                        // 这里的f[son][k],第二位是考虑了son的所有子树的,f[son][son_sons][k]
                        f[u][j] = Math.max(f[u][j], f[u][j - k] + f[son][k]); 
                    }
            }
        }
        
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            n = sc.nextInt();
            m = sc.nextInt();
            int root = -1;
            for (int i = 1; i <= n; i ++) {
                int vi = sc.nextInt(), wi = sc.nextInt(), pi = sc.nextInt();
                v[i] = vi;
                w[i] = wi;
                if (pi == -1) root = i;
                else {
                    add(pi, i);
                }
            }
            dfs(root);
            System.out.println(f[root][m]);
        }
    }
    
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/doubest/p/16100545.html
Copyright © 2020-2023  润新知