题目描述:
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
题解:
这是一个多维费用的 0-1 背包问题,有两个背包大小, 0 的数量和 1 的数量。我们在这里直接展示三维空间压缩到二维后的写法。
代码:
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
int N = strs.size();
vector<vector<int>>dp(m+1,vector<int>(n+1,0));
for(int i= 0;i<N;i++)
{
int l = strs[i].size();
int m_min=0,n_min=0;
for(int j = 0;j<l;j++)
{
if(strs[i][j]=='1')
n_min ++;
if(strs[i][j]=='0')
m_min ++;
}
for(int x = m;x>=m_min;x--)
{
for(int y = n;y>=n_min;y--)
{
dp[x][y] = max(dp[x-m_min][y-n_min]+1,dp[x][y]);
//dp[j] = dp[j],dp[j-x]+x
}
}
}
return dp[m][n];
}
};
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>>dp(m+1,vector<int>(n+1,0));
for(const string &str:strs)
{
auto [count0,count1] = count(str);
for(int i=m;i>=count0;i--)
for(int j=n;j>=count1;j--)
dp[i][j] = max(dp[i][j],dp[i-count0][j-count1]+1);
}
return dp[m][n];
}
pair<int,int> count(const string &S)
{
int count1=0,count0=0;
for(const char &s:S)
{
if(s=='1')
count1++;
else
count0++;
}
return make_pair(count0,count1);
}
};