在计算机界中,我们总是追求用有限的资源获取最大的收益。
现在,假设你分别支配着 m 个 0
和 n 个 1
。另外,还有一个仅包含 0
和 1
字符串的数组。
你的任务是使用给定的 m 个 0
和 n 个 1
,找到能拼出存在于数组中的字符串的最大数量。每个 0
和 1
至多被使用一次。
注意:
- 给定
0
和1
的数量都不会超过100
。 - 给定字符串数组的长度不会超过
600
。
示例 1:
输入: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3
输出: 4
解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出,即 "10","0001","1","0" 。
示例 2:
输入: Array = {"10", "0", "1"}, m = 1, n = 1
输出: 2
解释: 你可以拼出 "10",但之后就没有剩余数字了。更好的选择是拼出 "0" 和 "1" 。
题解:乍看本题,毫无思路,不过如果你熟悉二维费用的背包问题<传送门>(相关题目洛谷P1507),这道题目就变得简单了,好吧,假设你已经看懂基于二维费用的背包问题,那对应本题,0和1的数目分别对应的是拥有的资源,能组成的数字个数就是背包能装下的最大价值,跟根据二维费用的背包问题的动态转移方程,dp[i][j]=max(dp[i][j],d[i-s1[1]][j-s2[i]]+1);在这里dp[i][j]表示的意思是花费i和j数目的两种资源能获得的最大价值也就是本题中能组成的最大数字数目,s1[i]表示组成当前数字需要的0的个数,s2[i]表示组成当前数字需要的1的个数,整个动态转移方程基于是否组成当前数字来判断,d[i-s1[1]][j-s2[i]]+1就表示的是组成当前数字,d[i-s1[1]][j-s2[i]]表示没有组成当前数字时最优解,再加上当前数字就是组成当前数字之后的解,再进行比较确定是都是最优解。
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int l=strs.length;
int[][] dp=new int[m+1][n+1];
for(String str:strs){
int z=0,o=0;
for(int i=0;i<str.length();i++){
if(str.charAt(i)=='0')
z++;
else
o++;
}
for(int i=m;i>=z;i--){
for(int j=n;j>=o;j--){
dp[i][j]=Math.max(dp[i][j],dp[i-z][j-o]+1);
}
}
}
return dp[m][n];
}
}