力扣刷题474. 一和零
474. 一和零 - 力扣(LeetCode)
这一道题主要是把实际问题抽象为背包问题,对于每一个字符串的价值都是1,每一个字符串的体积由两部分组成,0和1的大小,所以判断时需要同时满足0和1的大小同时小于给定的01大小(背包容量)。
我们先求出每一个字符串的体积(0和1的个数),第一层循环即为遍历所有的字符串,内循环为双层循环,因为要同时满足两个条件,k为当前的字符串,i为背包0的容量,j为背包1的容量。可以推出递推公式为:
dp[k][i][j] = max( dp[k - 1][ i ][ j ] , dp[k - 1][ i - cnt[ k - 1][ 0 ] ][ j - cnt[ k - 1][ 1 ] +1 )
public class Main {
public static void main(String[] args) {
String[] strs = { "10", "0001", "111001", "1", "0" };
int m = 5;// m个0
int n = 3;// n个1
int a = findMaxForm(strs, m, n);
System.out.println(a);
}
public static int findMaxForm(String[] strs, int m, int n) {
int len = strs.length;
int[][] cnt = new int[len][2];
for (int i = 0; i < len; i++) {
String str = strs[i];
int ZeroCount = 0;
int OneCount = 0;
for (char c : str.toCharArray()) {
if (c == '0')
ZeroCount++;
else
OneCount++;
}
cnt[i][0] = ZeroCount;
cnt[i][1] = OneCount;
}
int[][][] dp = new int[len + 1][m + 1][n + 1];
for (int k = 1; k <= len; k++) {
int zero = cnt[k - 1][0];
int one = cnt[k - 1][1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
// 不选
int a = dp[k - 1][i][j];
// 选
int b = (i >= zero && j >= one) ? dp[k - 1][i - zero][j - one] + 1 : 0;
dp[k][i][j] = Math.max(a, b);
}
}
}
return dp[len][m][n];
}
}