Bicolorings
题意
有一个2*n的格子,每个格子可以涂成白色或黑色,然后 根据涂完的颜色可以分成连通块(白色跟白色连通,黑色跟黑色联通)然后 问连通块的数量是k的时候有多少种涂法。。
我还是菜了啊
想不到dp数组表示啥,想到了这个题就很简单了。
题解:
dp[1000][2000][4] 。
n是1000
k是2000
后面的4 表示 这竖上面是啥 00 01 10 11 这四种。
把二维变成一维 ,秒啊~~
dp[i][j][p] 表示 到第i列是p连通块为j的有多少种。
状态转移就很好算了。简单又暴力。。就不用说了。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1005;
typedef long long ll;
// 00 01 10 11
ll dp[maxn][2 * maxn][4];
const ll mod = 998244353;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
dp[1][1][0] = dp[1][1][3] = 1;
dp[1][2][1] = dp[1][2][2] = 1;
for (int i = 2; i <= n; i ++ )
{
for (int j = 1; j <= k; j ++ )
{
dp[i][j][0] = dp[i - 1][j][0] + dp[i - 1][j][1] + dp[i - 1][j][2] + dp[i - 1][j - 1][3];
dp[i][j][0] %= mod;
dp[i][j][1] = dp[i - 1][j - 1][0] + dp[i - 1][j][1] + dp[i - 1][j - 1][3];
if(j >= 2)
{
dp[i][j][1] += dp[i - 1][j - 2][2];
}
dp[i][j][1] %= mod;
dp[i][j][2] = dp[i - 1][j - 1][0] + dp[i - 1][j][2] + dp[i - 1][j - 1][3];
if(j >= 2)
{
dp[i][j][2] += dp[i - 1][j - 2][1];
}
dp[i][j][2] %= mod;
dp[i][j][3] = dp[i - 1][j - 1][0] + dp[i - 1][j][1] + dp[i - 1][j][2] + dp[i - 1][j][3];
dp[i][j][3] %= mod;
}
}
printf("%lld\n",(dp[n][k][0] + dp[n][k][1] + dp[n][k][2] + dp[n][k][3]) % mod);
}