题意
给定m个0个n个1,以及一堆字符串数组strs,要求你用这个m个0和n个1,去构成strs里面的字符串,求能够得到的最多字符串数目,可以剩余。
思路
就01背包,考虑第i个字符串是否选择。
状态表示:
d[i][j][k]
,去组成第i个字符串时,用了j个0,k个1能够得到的最多的字符串数目。
转移方程:
d[i][j][k]=max(d[i−1][j−Zi][k−Oi]+1,d[i−1][j][k])
其中
Zi
代表第i个字符串中0的数目,
Oi
代表第i个字符串中1的数目。
细节
滚动数组优化空间
m和n可以剩余
代码
const int maxn = 1000 + 5;
const int maxm = 100000 + 5;
int d[2][maxn][maxn];
int Z[maxm], O[maxm];
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
int nn = strs.size();
if (nn == 0) return 0;
memset(Z, 0, sizeof(Z));
memset(O, 0, sizeof(O));
memset(d, 0, sizeof(d));
for (int i = 0; i < strs.size(); i++) {
for (int j = 0; j < strs[i].length(); j++) {
if (strs[i][j] == '0') Z[i]++;
else O[i]++;
}
}
d[0][Z[0]][O[0]] += (Z[0] <= m && O[0] <= n ? 1 : 0);
int t = 0, res = d[0][Z[0]][O[0]];
for (int i = 1; i < nn; i++, t ^= 1) {
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
d[t ^ 1][j][k] = d[t][j][k];
if (j >= Z[i] && k >= O[i]) d[t ^ 1][j][k] = max(d[t][j - Z[i]][k - O[i]] + 1, d[t][j][k]);
res = max(res, d[t ^ 1][j][k]);
}
}
}
return res;
}
};