0-1背包
简介
0-1背包问题:给定n种物品和一背包。每种物品有着重量和价值两个属性,背包的有总容量限制。问应该如何选择装入背包中的物品,使得装入背包中物品的总价值最大?背包问题有很多种,0-1背包是最为基础的一种,其核心思想均为用动态规划来解决。
解法
设有以下几种物品:
物品(i) | 重量(\(w_i\)) | 价值(\(v_i\)) |
---|---|---|
物品0 | 1 | 2 |
物品1 | 2 | 3 |
物品2 | 3 | 4 |
物品3 | 4 | 5 |
物品4 | 5 | 6 |
背包总容量(\(w_a\))为8,如何选择物品才能让背包的能够装的价值最大?
通常解法
我们用\(dp[i][j]\)来表示仅从前i个物品里面选择且总容量为j时的物品的最大价值。动态转移方程可以写成如下形式:
\(dp[i][j] = max(dp[i-1][j-w[i]]+v[i],dp[i-1][j])\)
每遍历到一个物品的时候,这个物品有装或者不装两种选择,如果装这个物品,则装之后的最大价值为当前物品的价值加上不装之前(容量为\(j-w[i]\))的最大价值,如果不装,则最大价值为前i-1个物品的最大价值,这两者取最大值即可。示例源码如下。
1 | w = list(range(1, 6)) # 每个物品重量 |
- dp转移情况:
1 | [0, 2, 2, 2, 2, 2, 2, 2, 2] |
空间优化
在第二层遍历时\(j\)的状态由\(j\)之前的状态来决定,而\(j\)不会影响到它之前的状态,因此可以用一维数组存储变量,然后倒序更改此数组,将空间复杂度优化到\(O(w_a)\)
1 | w = list(range(1, 6)) # 每个物品重量 |