01背包问题
什么是01背包问题
01背包问题是最基本的背包问题之一,它是一个NP完全问题,通常被用来讲解动态规划算法的基本思想和方法。在01背包问题中,物品有两种属性,体积和价值,每个物品只有一件,背包有一定的容量限制,问如何选择物品,使得背包中所装物品的价值最大。
动态规划解法
由于01背包问题满足无后效性和最优子结构性质,因此可以采用动态规划来求解。具体的动态规划算法如下:
设dp[i][j]表示前i件物品放入容量为j的背包中所能获得的最大价值,其中i取值范围为[0, n],表示前i件物品可以进行选择,j取值范围为[0, m],表示背包的容量可以取值为从0到m.
则dp[i][j]的状态转移方程为:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
其中,w[i]和v[i]分别表示第i件物品的重量和价值。
我们可以递归的求解dp[i][j],当最终dp[n][m]求解出来之后,即为所求的最大价值。
代码实现
def knapsack(n, m, w, v):
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):
if w[i] > j:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
return dp[n][m]
示例说明
示例一
考虑一个简单的01背包问题,假设背包容量为10,共有4件物品,其重量和价值分别如下:
物品 | 重量 | 价值 |
---|---|---|
1 | 2 | 6 |
2 | 2 | 3 |
3 | 6 | 5 |
4 | 5 | 4 |
则运行代码可以得到答案为:
w = [0, 2, 2, 6, 5]
v = [0, 6, 3, 5, 4]
print(knapsack(4, 10, w, v))
结果为:
17
即在背包容量为10的情况下,我们可以选择物品1、3和4,它们的价值之和为17,是最优的。
示例二
考虑一个稍微复杂一些的01背包问题,假设背包容量为10,共有5件物品,其重量和价值分别如下:
物品 | 重量 | 价值 |
---|---|---|
1 | 2 | 6 |
2 | 3 | 4 |
3 | 4 | 5 |
4 | 5 | 6 |
5 | 7 | 8 |
则运行代码可以得到答案为:
w = [0, 2, 3, 4, 5, 7]
v = [0, 6, 4, 5, 6, 8]
print(knapsack(5, 10, w, v))
结果为:
15
即在背包容量为10的情况下,我们可以选择物品2和3,它们的价值之和为15,是最优的。