题目描述
解题思路
本题注意区分多重背包和0-1背包。
本题可以抽象为2个背包,0的个数和1的个数分别代表2个维度的背包。
- 确定dp数组(dp table)以及下标的含义
 
dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
- 确定递推公式
 
dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zeroNum个0,oneNum个1。
dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。
zeroNum和oneNum代表重量,而value表示则是字符串本身的个数。
- dp数组如何初始化
 
因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。
- 确定遍历顺序
 
两个维度遍历,但是背包遍历还是要按照倒序遍历
- 举例推导dp数组
 
以输入:[“10”,”0001”,”111001”,”1”,”0”],m = 3,n = 3为例
public int findMaxForm(String[] strs, int m, int n) {int[][] dp = new int[m + 1][n + 1];// 遍历物品for (String str : strs) {char[] chars = str.toCharArray();int zeroNum = 0, oneNums = 0;for (int i = 0; i < chars.length; i++) {if (chars[i] == '1') {oneNums++;} else {zeroNum++;}}// 遍历2个背包for (int i = m; i >= zeroNum; i--) {for (int j = n; j >= oneNums; j--) {dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNums] + 1);}}}return dp[m][n];}
