LeetCode 3130.找出所有稳定的二进制数组II

题目描述

原题链接:LeetCode 3130.找出所有稳定的二进制数组II

解题思路

动态规划( o ( n 2 ) o(n^2) o(n2)

定义dp0[i][j]为以 0 0 0结尾的有着 i i i 0 0 0 j j j 1 1 1的稳定的二进制数组的数目,定义dp1[i][j]为以 1 1 1结尾的有着 i i i 0 0 0 j j j 1 1 1的稳定二进制数组的数目。
对于dp0[i][j]的更新,我们可以先进行分类讨论:

  1. i ≤ m i n ( l i m i t , z e r o ) , j = 0 i \le min(limit,zero),j=0 imin(limit,zero),j=0时,有且仅有一种方案,就是全为 1 1 1
  2. j ≠ 0 j \ne 0 j=0时,又可以分为两种情况:
    1. i ≤ l i m i t i \le limit ilimit时,dp0[i][j]可以由dp0[i-1][j]dp1[i-1][j]更新而来,dp0[i][j]=dp0[i-1][j]+dp1[i-1][j]
    2. i > l i m i t i \gt limit i>limit时,dp0[i-1][j]dp1[i-1][j]中只有一种情况不满足添加 1 1 1 0 0 0之后,连续 0 0 0的数量不大于 l i m i t limit limit,就是当后面 l i m i t limit limit个数都是 0 0 0的时候。这时候的方案数与dp1[i-1-limit][j]相同。这里是dp0而不是dp1是因为假如是dp0,那么也就是说这个数组有不止 l i m i t limit limit 0 0 0,也就不满足题意。这个时候的状态转移方程为:dp0[i][j]=dp0[i-1][j]+dp1[i-1][j]-dp1[i-1-limit][j]
  3. i = 0 i=0 i=0时,不存在满足题意的方案。dp0[i][j]=0

同理也可以得到dp1[i][j]的状态转移方程。总的状态转移方程如下:
d p 0 [ i ] [ j ] = { 1 , i f   i   ≤ m i n ( l i m i t , z e r o )   a n d   j = 0 d p 0 [ i − 1 ] [ j ] + d p 1 [ i − 1 ] [ j ] , i f   i ≤ l i m i t   a n d   j ≠ 0 d p 0 [ i − 1 ] [ j ] + d p 1 [ i − 1 ] [ j ] − d p 1 [ i − 1 − l i m i t ] [ j ] , i f   i > l i m i t   a n d   j ≠ 0 0 , i f   i = 0 dp0[i][j]= \begin{cases} 1, &if\ i\ \le min(limit,zero) \ and \ j=0 \\ dp0[i-1][j]+dp1[i-1][j], &if\ i \le limit\ and \ j \ne0 \\ dp0[i-1][j]+dp1[i-1][j]-dp1[i-1-limit][j], &if \ i \gt limit \ and \ j \ne 0 \\ 0, &if \ i=0 \end{cases} dp0[i][j]= 1,dp0[i1][j]+dp1[i1][j],dp0[i1][j]+dp1[i1][j]dp1[i1limit][j],0,if i min(limit,zero) and j=0if ilimit and j=0if i>limit and j=0if i=0
d p 1 [ i ] [ j ] = { 1 , i f   j   ≤ m i n ( l i m i t , o n e )   a n d   i = 0 d p 0 [ i ] [ j − 1 ] + d p 1 [ i ] [ j − 1 ] , i f   j ≤ l i m i t   a n d   i ≠ 0 d p 0 [ i ] [ j − 1 ] + d p 1 [ i ] [ j − 1 ] − d p 0 [ i ] [ j − 1 − l i m i t ] , i f   j > l i m i t   a n d   i ≠ 0 0 , i f   j = 0 dp1[i][j]= \begin{cases} 1, &if\ j\ \le min(limit,one) \ and \ i=0 \\ dp0[i][j-1]+dp1[i][j-1], &if\ j \le limit\ and \ i \ne0 \\ dp0[i][j-1]+dp1[i][j-1]-dp0[i][j-1-limit], &if \ j \gt limit \ and \ i \ne 0 \\ 0, &if \ j=0 \end{cases} dp1[i][j]= 1,dp0[i][j1]+dp1[i][j1],dp0[i][j1]+dp1[i][j1]dp0[i][j1limit],0,if j min(limit,one) and i=0if jlimit and i=0if j>limit and i=0if j=0

###C++代码

class Solution {
public:
    typedef long long LL;
    int numberOfStableArrays(int zero, int one, int limit) {
        LL dp1[1010][1010] = {0};
        LL dp0[1010][1010] = {0};
        LL mod = 1e9+7;
        for(int i = 1; i <= min(limit, zero); i++) {
            dp0[i][0] = 1;
        }
        for(int j = 1; j <= min(limit, one); j++) {
            dp1[0][j] = 1;
        }
        for(int i = 1; i <= zero; i++) {
            for(int j = 1; j <= one; j++) {
                if(i <= limit) {
                    dp0[i][j] = dp0[i-1][j]+dp1[i-1][j];
                } else {
                    dp0[i][j] = dp0[i-1][j]+dp1[i-1][j]-dp1[i-1-limit][j];
                }
                dp0[i][j] = (dp0[i][j] % mod+mod)%mod;

                if(j <= limit) {
                    dp1[i][j] = dp0[i][j-1]+dp1[i][j-1];
                } else {
                    dp1[i][j] = dp0[i][j-1]+dp1[i][j-1]-dp0[i][j-1-limit];
                }
                dp1[i][j] = (dp1[i][j] % mod+mod)%mod;
            }
        }
        return (dp0[zero][one]+dp1[zero][one])%mod;
    }
};

注意: 在对结果进行取余的时候要注意防止出现负数,因此要先加上一个 1 0 9 + 7 10^9+7 109+7再取余。如果不那么做,那么在dp0[i][j] = dp0[i-1][j]+dp1[i-1][j]-dp1[i-1-limit][j];的时候,由于dp0[i-1][j]+dp1[i-1][j]虽然比dp1[i-1-limit][j]大,但是由于前一项取余之后可能很小,后一项取余之后也可能很大,因此相减可能出现负数,如果不处理可能导致最终的结果为负。

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值