动态规划:01 背包(闫氏DP分析法)

动态规划:01 背包(闫氏DP分析法)

01 背包

www.acwing.com/problem/content/2/

DP:

  • 状态表示 f(i, j)​

    • 集合:所有只考虑前 i i i 个物品,且总体积不超过 j j j 的选项的集合

    • 属性:max

      • 最终答案:f(N, V)
  • 状态计算:f(i, j) = max(f(i - 1, j), f(i - 1, j - v[i]) + w[i])​

    • 选第 i i i 个物品:所有包含第 i i i 个物品的选项集合,其实需要找的就是变化的部分的最大值,即:从 1 1 1~ i − 1 i-1 i−1 中选择,且总体积小于等于 j − v i j-vi j−vi 的选项集合

      当 j < v i j < vi j<vi 时,该分支不存在

      • 变化的部分:包含前 i − 1 i-1 i−1 个物品的不同选项
      • 不变的部分:都需要包含第 i i i 个物品
    • 不选第 i i i 个物品:需要满足从 1 1 1~ i − 1 i-1 i−1 中选择,且总体积小于等于 j j j 的所有选项集合

二维朴素写法

java 复制代码
import java.util.*;

public class Main {
    static final int N = 1010;
    // f[i][j] 表示只对于前i个物品且使用j的背包空间,选取的所有方案中的最大值
    static int[][] f = new int[N][N];
    static int[] w = new int[N];
    static int[] v = new int[N];
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int V = sc.nextInt();
        
        for (int i = 1; i <= n; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }
        
        // dp
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= V; j++) {
                if (j >= v[i]) {
                    // j >= v[i] 能够将第i个物品放入
                    // 放入第i个物品
                    f[i][j] = f[i - 1][j - v[i]] + w[i];
                }
                // 不放入第i个物品
                f[i][j] = Math.max(f[i][j], f[i - 1][j]);
            }
        }
        
        System.out.println(f[n][V]);
    }
}

一维优化写法

java 复制代码
import java.util.*;

public class Main {
    static final int N = 1010;
    // 一维优化,相当于每次的i直接覆盖在上一次的i-1数组上
    // 因为每一次只会用到上一层的,不会用到更上面的数据
    // 且每次j-v[i]只会用在j之前的,当使用从大到小遍历时,当前修改不会影响到后面的答案
    // 所以可以使用滚动数组优化
    static int[] f = new int[N];
    static int[] w = new int[N];
    static int[] v = new int[N];
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int V = sc.nextInt();
        
        for (int i = 1; i <= n; i++) {
            v[i] = sc.nextInt();
            w[i] = sc.nextInt();
        }
        
        // dp
        for (int i = 1; i <= n; i++) {
            // 想清楚为什么要从大到小
            // 因为遍历到j时要使用上一层的j-v[i],所以应当先遍历大的才能避免影响
            for (int j = V; j >= 0; j--) {
                if (j >= v[i]) {
                    // j >= v[i] 能够将第i个物品放入
                    // 不放入第i个物品, 放入第i个物品
                    f[j] = Math.max(f[j], f[j - v[i]] + w[i]);    
                }
            }
        }
        
        System.out.println(f[V]);
    }
}
相关推荐
秋天的怀念_David3 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
专业程序开发源3 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
秋天的怀念_David4 小时前
算法一千零一夜 · 第十四夜 幻方与奇妙的二进制
java·程序人生·算法
thefool1122664 小时前
网络编程^
java
薛定e的猫咪4 小时前
(ICLR 2020)MAML 靠的不是快速学习,而是特征复用
人工智能·深度学习·学习·算法·机器学习
薛定e的猫咪4 小时前
(ICLR 2026)DF-META:面向 FJSP 的无导数元学习实例自适应调度
人工智能·深度学习·学习·算法·机器学习
Thinker QAQ4 小时前
并发编程(十一):Shared Memory 与 Message Passing——关系与组合使用
java·python·go·并发编程·shared memory·message passing
齐 飞5 小时前
idea中git误操作撤回git reset --hard ‘HEAD@{1}‘
java·git·intellij-idea
你的保护色5 小时前
多AS互联BGP4综合实验设计
java
某不知名網友5 小时前
ROS2进阶:服务通信、自定义SRV接口、参数服务器与基于服务的参数通信详解
java·开发语言·microsoft