题目:https://codeforces.com/problemset/problem/1051/D

题意:一个2行n列的矩形,上面有黑白块,然后问你怎么布置才能有k个连通块,问有多少种方案数

思路:其实就是一个矩阵,我们一次放一列

四种状态    

黑    |   白 | 白 | 黑

白  |  黑 | 白 | 黑

我们dp[n][m][k],第n列第m种状态k个连通块的方案数,现在我们算放每个状态时,计算一次增加了多少个连通块

因为数组太大了,所以我们用滚动数组

然后递推就行了

#include<bits/stdc++.h>
#define maxn 2005
#define mod 998244353 
using namespace std;
typedef long long ll;
ll dp[2][4][maxn];
ll n,k;
int main(){
    cin>>n>>k;
    dp[0][0][2]=1;// 0 1
    dp[0][1][2]=1;// 1 0
    dp[0][2][1]=1;// 1 1
    dp[0][3][1]=1;// 0 0
    for(int i=2;i<=n;i++){
        for(int j=0;j<=k;j++){
            dp[1][0][j]=dp[0][0][j];
            dp[1][1][j]=dp[0][1][j];
            dp[1][2][j]=((dp[0][0][j]+dp[0][1][j])%mod+dp[0][2][j])%mod;
            dp[1][3][j]=((dp[0][0][j]+dp[0][1][j])%mod+dp[0][3][j])%mod;
            if(j-2>=0){
                dp[1][0][j]=(dp[1][0][j]+dp[0][1][j-2])%mod;
                dp[1][1][j]=(dp[1][1][j]+dp[0][0][j-2])%mod;
            }
            if(j-1>=0){
                dp[1][2][j]=(dp[1][2][j]+dp[0][3][j-1])%mod;
                dp[1][3][j]=(dp[1][3][j]+dp[0][2][j-1])%mod;
                dp[1][0][j]=((dp[1][0][j]+dp[0][2][j-1])%mod+dp[0][3][j-1])%mod;
                dp[1][1][j]=((dp[1][1][j]+dp[0][2][j-1])%mod+dp[0][3][j-1])%mod;
            }
        }
        for(int j=0;j<=k;j++){
            for(int z=0;z<=3;z++){
                dp[0][z][j]=dp[1][z][j];
                dp[1][z][j]=0;
            }
        }
    } 
    ll sum=((dp[0][0][k]+dp[0][1][k])%mod+(dp[0][2][k]+dp[0][3][k])%mod)%mod;
    printf("%lld",sum);
}