刷题笔记 | 0-1背包最大价值问题 | 豆包MarsCode AI刷题

50 阅读3分钟

0-1背包理论知识

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

动态规划-背包问题

解题思路

回溯3问:

  1. 当前操作?枚举第i个物品选或不选: 不选,剩余容量不变;选,剩余容量减少w[i]

  2. 子问题?在剩余容量为C时, 从前i个物品中得到的最大价值和

  3. 下一个子问题?分类讨论:

    不选:在剩余容量为c时, 从前i-1个物品中得到的最大价值和

    选: 在剩余容量为 c - w[i] 时, 从前i-1个物品中得到的最大价值和

问题描述

一个旅行者外出旅行时需要将 n 件物品装入背包,背包的总容量为 m。每个物品都有一个重量和一个价值。你需要根据这些物品的重量和价值,决定如何选择物品放入背包,使得在不超过总容量的情况下,背包中物品的总价值最大。

给定两个整数数组 weights 和 values,其中 weights[i] 表示第 i 个物品的重量,values[i] 表示第 i 个物品的价值。你需要输出在满足背包总容量为 m 的情况下,背包中物品的最大总价值。

测试样例

样例1:

输入:n = 3 ,weights = [2, 1, 3] ,values = [4, 2, 3] ,m = 3
输出:6

样例2:

输入:n = 4 ,weights = [1, 2, 3, 2] ,values = [10, 20, 30, 40] ,m = 5
输出:70

解题思路

  1. 定义状态:我们可以使用一个二维数组 dp,其中 dp[i][j] 表示在前 i 个物品中,背包容量为 j 时的最大价值。

  2. 状态转移方程

    • 如果不选择第 i 个物品,那么 dp[i][j] = dp[i-1][j]
    • 如果选择第 i 个物品,那么 dp[i][j] = dp[i-1][j-weights[i]] + values[i]
    • 最终的状态转移方程为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-weights[i]] + values[i])
  3. 初始化dp[0][j] 应该初始化为0,因为没有任何物品时,最大价值为0。

  4. 最终结果dp[n][m] 即为所求的最大价值。

public class Main {
    public static int solution(int n, int[] weights, int[] values, int m) {
        // 创建一个二维数组 dp,大小为 (n+1) x (m+1)
        int[][] dp = new int[n + 1][m + 1];

        // 初始化 dp 数组
        // 这里可以省略,因为 Java 中数组默认初始化为 0

        // 填充 dp 数组
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                // 不选择第 i 个物品
                dp[i][j] = dp[i - 1][j];

                // 如果当前背包容量 j 大于等于第 i 个物品的重量
                if (j >= weights[i - 1]) {
                    // 选择第 i 个物品
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);
                }
            }
        }

        // 返回最大价值
        return dp[n][m];
    }

    public static void main(String[] args) {
        System.out.println(solution(3, new int[]{2, 1, 3}, new int[]{4, 2, 3}, 3) == 6);
        System.out.println(solution(4, new int[]{1, 2, 3, 2}, new int[]{10, 20, 30, 40}, 5) == 70);
        System.out.println(solution(2, new int[]{1, 4}, new int[]{5, 10}, 4) == 10);
    }
}