问题:给定t个01字符串S[0],...,S[t-1],现有m个0,n个1,问最多能组成多少个给定字符串,每个字符串最多组成一次。
例:
输入:
S = ["10","0001","111001","1","0"],m = 5,n = 3
输出:4("10","0001","1","0")
跟背包问题有点类似,我们考虑最后一个字符串S[t-1]有没有消耗01个数被组成
case1:S[t-1]没有被组成,则需要知道S[0],...,S[t-2],消耗m个0、n个1组成最多的字符串个数
case2:S[t-1]被组成,设S[t-1]里有a[t-1]个0,b[t-1]个1,则需要知道
S[0],...,S[t-2],消耗m-a[t-1]个0、n-b[t-1]个1组成最多的字符串个数
子问题:设f[i][j][k]表示前i个01字符串S[0],...,S[i-1]最多能由j个0和k个1组成最多的字符串个数;
S[i-1]里有a[i-1]个0,b[i-1]个1
f[i][j][k] = max{ f[i-1][j][k] , f[i-1][j-a[i-1]][k-b[i-1]] + 1 | j >= a[i-1] and k >= b[i-1] }
max{ case1 , case2 }
初始情况:
f[0][0,...,m][0,...,n] = 0;没有字符串可以组成,
f[i-1][j-a[i-1]][k-b[i-1]] + 1 | j >= a[i-1] and k >= b[i-1] ;下标要为非负
计算顺序:
f[0][0][0],...f[t][m][n];
答案:f[t][m][n]
时间复杂度O(tmn),空间复杂度O(tmn),可以优化至O(mn)
代码及注释如下:
def Ones_And_Zeroes(S,m,n):
t = len(S)
#创建时赋初值,f[0][0,...,m][0,...,n] = 0;没有字符串可以组成,
f = [[[0 for i in range(n+1)] for j in range(m+1)] for k in range(t+1)]
for i in range(1,t+1):
for j in range(m+1):
for k in range(n+1):
#case1
f[i][j][k] = f[i-1][j][k]
#case2
if j >= S[i-1].count('0') and k >= S[i-1].count('1') :
f[i][j][k] = max( f[i][j][k] , f[i-1][j-S[i-1].count('0')][k-S[i-1].count('1')] + 1 )
return f[t][m][n]
S = ["10","0001","111001","1","0"]
m = 5
n = 3
print(Ones_And_Zeroes(S,m,n))
#答案:4
优化空间和之前一样,利用old和new滚动数组即可,这里不再给出代码了=-=