问题描述
一个旅行者外出旅行时需要将 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 背包问题,目标是在给定物品的重量和价值的情况下,选择哪些物品放入背包,使得背包的总价值最大,并且背包的总重量不超过容量限制。
问题分析
- 每个物品有一个重量
weights[i]和一个价值values[i]。 - 背包的容量为
m,我们需要选择一些物品放入背包,要求不超过容量m,同时背包中物品的总价值最大。
动态规划解法
我们可以使用 动态规划 来解决这个问题。动态规划的思路如下:
- 使用一个数组
dp,其中dp[j]表示背包容量为j时,能够获得的最大价值。 - 我们初始化
dp[0] = 0,表示容量为 0 时,背包中的价值为 0。 - 对于每个物品
i,我们尝试放入背包,并更新相应的dp[j],其中j是背包的容量。我们需要逆序更新dp,避免在更新dp时使用同一个物品多次。 - 对于每个容量
j(从大到小),如果当前物品i的重量weights[i]小于等于j,我们就尝试将物品放入背包,更新最大价值为dp[j] = max(dp[j], dp[j - weights[i]] + values[i])。
代码实现
python
复制代码
def solution(n: int, weights: list, values: list, m: int) -> int:
# dp[j] 表示容量为 j 的背包所能获得的最大价值
dp = [0] * (m + 1)
# 遍历每个物品
for i in range(n):
# 从背包最大容量 m 开始,逐渐往小容量更新,防止重复选择
for j in range(m, weights[i] - 1, -1):
dp[j] = max(dp[j], dp[j - weights[i]] + values[i])
# 最后返回最大容量 m 时的最大价值
return dp[m]
# 测试用例
if __name__ == '__main__':
print(solution(3, [2, 1, 3], [4, 2, 3], 3)) # 6
print(solution(4, [1, 2, 3, 2], [10, 20, 30, 40], 5)) # 70
print(solution(2, [1, 4], [5, 10], 4)) # 10
解释
- dp数组:
dp[j]表示容量为j的背包能够获得的最大价值。初始化时,dp[0]为0,表示背包容量为 0 时没有物品可以放入,因此最大价值为 0。 - 物品选择:对于每个物品,我们从背包容量的最大值
m开始,逐步向小容量更新dp。我们从大到小更新是为了避免同一个物品被多次选取。 - 状态转移:对于每个物品
i,如果背包当前容量j大于等于物品的重量weights[i],则可以选择放入该物品,更新最大价值为dp[j] = max(dp[j], dp[j - weights[i]] + values[i])。 - 最终结果:在遍历所有物品后,
dp[m]就是背包容量为m时能够获得的最大价值。
时间复杂度
- 时间复杂度:
O(n * m),其中n是物品的数量,m是背包的容量。我们需要遍历所有物品,对于每个物品,我们遍历背包容量从m到weights[i]。 - 空间复杂度:
O(m),我们只需要一个大小为m+1的数组dp来存储最大价值。
测试结果
- 对于输入
n = 3, weights = [2, 1, 3], values = [4, 2, 3], m = 3,输出应为6。 - 对于输入
n = 4, weights = [1, 2, 3, 2], values = [10, 20, 30, 40], m = 5,输出应为70。 - 对于输入
n = 2, weights = [1, 4], values = [5, 10], m = 4,输出应为10。
这样就能够解决这个背包问题,得出最大价值。