一、题目描述

二、解题思路
解法一:深度优先搜索+剪枝(超时)
本题实际上与0/1背包问题类似,即子集问题的变种,可以采用深度优先搜索+剪枝来解决这个问题,对于每一个字符串,只有选择和不选择两种决策。
解法二:动态规划
dp[i][j]表示m=i,n=j时,最大的子集数,对于每一个字符串,只有选择与不选择两种情况,所以dp[i][j]=max(dp[i][j],dp[i-zeros][j-ones]),这就是状态转移方程,依此来写就可以了。
三、代码实现
解法一:深度优先搜索+剪枝(超时)
cpp
class Solution {
int length;
vector<vector<int>> count;
public:
int findMaxForm(vector<string>& strs, int m, int n) {
//初始化全局变量
length=0;
//初始化count数组,记录每个字符串中'0'和'1'的个数
count.resize(strs.size(),vector<int>(2,0));
for(int i=0;i!=strs.size();i++){
for(auto ch:strs[i]){
if(ch=='0') count[i][0]++;
else if(ch=='1') count[i][1]++;
}
}
dfs(strs,0,m,n,0);
return length;
}
void dfs(vector<string>& strs,int start,int m,int n,int currentLength){
//递归出口
if(start==strs.size()){
length=max(length,currentLength);
return ;
}
//当前字符串的'1'和'0'的数量
int zeros=count[start][0];
int ones=count[start][1];
//选
if(m>=zeros&&n>=ones)
dfs(strs,start+1,m-zeros,n-ones,currentLength+1);
//不选
dfs(strs,start+1,m,n,currentLength);
}
};
解法二:动态规划(可通过)
cpp
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
//动态规划
//dp[i][j]表示m=i,n=j时,最大子集的长度
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
for(auto str:strs){
int zeros=count(str.begin(),str.end(),'0');
int ones=(int)str.size()-zeros;
//填写dp数组
for(int i=m;i>=zeros;i--)
for(int j=n;j>=ones;j--)
dp[i][j]=max(dp[i][j],dp[i-zeros][j-ones]+1);
}
return dp[m][n];
}
};