https://codeforces.com/problemset/problem/1051/D
题目大意:给一个
2
∗
n
2*n
2∗n的矩阵,每一个位置要么为黑色要么为白色,相邻且颜色相同的方块算作一个连通块,给定
k
k
k,问有多少种着色方法使得这个矩阵中恰好有
k
k
k个连通块。
思路:比较容易想到用
d
p
dp
dp来做,考虑用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示前
i
i
i列中连通块个数为
j
j
j时的着色方案数,但是这样比较难写出转移方程,然后因为这个矩阵只有两行,所以我们可以再多加一维来表示第
i
i
i列的状态,也就是用
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示前
i
i
i列连通块个数为
j
j
j且第
i
i
i列状态为
k
k
k时的着色方案数。其中
k
=
0
、
1
、
2
、
3
k=0、1、2、3
k=0、1、2、3,若用
0
0
0表示该位置为白色,
1
1
1表示该位置为黑色,则
k
=
0
k=0
k=0代表该列状态为
00
00
00,
k
=
1
k=1
k=1代表
01
01
01,
k
=
2
k=2
k=2代表
10
10
10,
k
=
3
k=3
k=3代表
11
11
11,这样就很好写出转移方程了。(代码中第二维和第三维交换了一下)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int maxn=1005;
int n,k;
ll dp[maxn][4][maxn<<1];
int main()
{
scanf("%d%d",&n,&k);
dp[1][0][1]=dp[1][1][2]=dp[1][2][2]=dp[1][3][1]=1;
for(int i=2;i<=n;i++)
{
int t=2*i;
for(int j=1;j<=t;j++)
{
dp[i][0][j]=dp[i-1][0][j]+dp[i-1][1][j]+dp[i-1][2][j];
dp[i][1][j]=dp[i-1][1][j];
dp[i][2][j]=dp[i-1][2][j];
dp[i][3][j]=dp[i-1][1][j]+dp[i-1][2][j]+dp[i-1][3][j];
if(j>=2)
{
dp[i][1][j]+=dp[i-1][0][j-1],dp[i][2][j]+=dp[i-1][0][j-1],dp[i][3][j]+=dp[i-1][0][j-1];
dp[i][0][j]+=dp[i-1][0][j-1],dp[i][1][j]+=dp[i-1][0][j-1],dp[i][2][j]+=dp[i-1][0][j-1];
}
if(j>=3)
{
dp[i][2][j]+=dp[i-1][1][j-2];
dp[i][1][j]+=dp[i-1][2][j-2];
}
for(int t=0;t<=3;t++)
if(dp[i][t][j]>=mod)
dp[i][t][j]%=mod;
}
}
ll ans=0;
ans=dp[n][0][k]+dp[n][1][k]+dp[n][2][k]+dp[n][3][k];
ans%=mod;
printf("%lld\n",ans);
return 0;
}