详细讲解部分背包问题的作用与使用方法
简介
部分背包问题是动态规划算法中常见的一类问题,它是 0/1 背包问题的变种,区别在于在部分背包问题中,每个物品的重量和价值都可以是一个非负数任意实数,而在 0/1 背包问题中每个物品的重量和价值必须是一个整数。
问题形式
部分背包问题描述如下:
有一个容量为 V 的背包和 n 个物品,第 i 个物品的重量为 w[i],价值为 v[i]。选定一些物品放入背包中,使得背包中物品的总重量不超过容量 V,且背包中物品的总价值最大。
解法
使用动态规划的思想解决部分背包问题。定义一个二维数组 dp,其中 dp[i][j] 代表在前 i 个物品中选择若干个放入容量为 j 的背包中所获得的最大价值。则有以下递推式:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]), 1<=i<=n, w[i] <=j<=V
其中 dp[i-1][j] 表示不选第 i 个物品,dp[i-1][j-w[i]]+v[i] 表示选第 i 个物品。
实现
以下是部分背包问题的 Python3 代码实现:
def knapsack(w, v, V):
n = len(w)
dp = [0] * (V + 1)
for i in range(n):
for j in range(V, w[i] - 1, -1):
dp[j] = max(dp[j], dp[j - w[i]] + v[i])
return dp[V]
示例说明
示例1
假设有一些物品,重量分别为 2, 3, 5, 7, 1,价值分别为 5, 8, 9, 4, 3。现在有一个容量为 10 的背包,求放置哪些物品能使得背包中物品的总价值最大。
w = [2, 3, 5, 7, 1]
v = [5, 8, 9, 4, 3]
V = 10
print(knapsack(w, v, V)) # 26
上面的代码中,可以看到在容量为 10 的背包中,可以放置第一个物品、第二个物品、第三个物品、第五个物品,选择这些物品最终能够得到价值总和为 26 的最优解。
示例2
假设有一些物品,重量分别为 1.2, 2.5, 3.7, 5.1, 2.2,价值分别为 8.1, 7.5, 6.3, 3.6, 4.7。现在有一个容量为 8 的背包,求放置哪些物品能使得背包中物品的总价值最大。
w = [1.2, 2.5, 3.7, 5.1, 2.2]
v = [8.1, 7.5, 6.3, 3.6, 4.7]
V = 8
print(knapsack(w, v, V)) # 19.5
上面的代码中,可以看到在容量为 8 的背包中,可以放置第一、第二、第五个物品,选择这些物品最终能够得到价值总和为 19.5 的最优解。