dp基础之Ones and Zeroes

问题:给定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滚动数组即可,这里不再给出代码了=-=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值