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

35 阅读3分钟

问题描述

一个旅行者外出旅行时需要将 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

样例3

输入:n = 2 ,weights = [1, 4] ,values = [5, 10] ,m = 4

输出:10

解题思路

这个问题是典型的0/1背包问题,它可以通过动态规划来解决。动态规划的关键在于构建一个二维数组dp,其中dp[i][j]表示在只考虑前i个物品时,背包容量为j可以获得的最大价值。

以下是解决这个问题的动态规划算法的步骤:

  1. 初始化一个二维数组dp,大小为(n+1) * (m+1),所有元素初始化为0。dp[i][j]表示考虑前i个物品,背包容量为j时的最大价值。

  2. 遍历每个物品,对于每个物品,更新dp数组。对于每个物品i和每个可能的背包容量j,我们有两种选择:

    • 不放入第i个物品,那么dp[i][j]的值就是dp[i-1][j]
    • 放入第i个物品,那么dp[i][j]的值就是dp[i-1][j-weights[i]] + values[i](前提是j大于等于weights[i])。
  3. 我们需要选择这两种情况中的最大值作为dp[i][j]的值。

  4. 最终,dp[n][m]就是我们要找的最大价值。

代码实现

def solution(n: int, weights: list, values: list, m: int) -> int:
    # 初始化动态规划表格,额外添加一行和一列用于处理边界情况 
    dp = [[0 for _ in range(m + 1)] for _ in range(n + 1)]

    # 填充动态规划表格
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            # 如果当前物品i的重量大于当前背包容量j,则不包括当前物品
            if weights[i - 1] > j:
                dp[i][j] = dp[i - 1][j]
            else:
                # 选择价值最大的方案:不包括当前物品的价值 或 包括当前物品的价值(如果包括,则剩余容量为j - weights[i - 1])
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1])

    # 返回背包的最大价值
    return dp[n][m]

if __name__ == '__main__':
    print(solution(n = 3, weights = [2, 1, 3], values = [4, 2, 3], m = 3) == 6)
    print(solution(n = 4, weights = [1, 2, 3, 2], values = [10, 20, 30, 40], m = 5) == 70)
    print(solution(n = 2, weights = [1, 4], values = [5, 10], m = 4) == 10)
    
'''