CodeForces - 1051D Bicolorings(dp) 解题报告
xzc 2019/3/30
题意:
给一个2行n列的格子(n<=1000),矩阵的每个单元都可以涂黑色或白色。颜色相同且相邻的是一个连通块。问在这个2*n的格子里面涂色,能构造出K(1<=k<=2n)个连通块的方案数是多少?(答案对998244353取模)
样例:
Input
3 4
Output
12
Input
4 1
Output
2
Input
1 2
Output
2
思路:
- 肯定是dp
- 我们下面来定义状态,对于某一列:
黑黑(BB) 为状态0
黑白(BW) 为状态1
白黑(WB) 为状态2
黑白(WW) 为状态3 - 定义dp[i][j][k]为i列格子,连通块数量为j,最后一列状态为kd的构造方案数(因为从i列到i+1列连通块数量的变化只和第i列有关)
第i列状态 第i+1列的状态 连通块增加的个数
B => B 0
B B
B => B 1
B W
B => W 1
B B
B => W 1
B W
—————————————————————
B => B 0
W B
B => B 0
W W
B => W 2
W B
B => W 0
W W
—————————————————————
W => B 0
B B
W => B 2
B W
W => W 0
B B
W => W 0
B W
—————————————————————
W => B 1
W B
W => B 1
W W
W => W 1
W B
W => W 0
W W
—————————————————————
dp转移方程:
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][0]) % mod;
dp[i+1][j+1][1] = (dp[i+1][j+1][1] + dp[i][j][0]) % mod;
dp[i+1][j+1][2] = (dp[i+1][j+1][2] + dp[i][j][0]) % mod;
dp[i+1][j+1][3] = (dp[i+1][j+1][3] + dp[i][j][0]) % mod;
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][1]) % mod;
dp[i+1][j+0][1] = (dp[i+1][j+0][1] + dp[i][j][1]) % mod;
dp[i+1][j+2][2] = (dp[i+1][j+2][2] + dp[i][j][1]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][1]) % mod;
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][2]) % mod;
dp[i+1][j+2][1] = (dp[i+1][j+2][1] + dp[i][j][2]) % mod;
dp[i+1][j+0][2] = (dp[i+1][j+0][2] + dp[i][j][2]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][2]) % mod;
dp[i+1][j+1][0] = (dp[i+1][j+1][0] + dp[i][j][3]) % mod;
dp[i+1][j+1][1] = (dp[i+1][j+1][1] + dp[i][j][3]) % mod;
dp[i+1][j+1][2] = (dp[i+1][j+1][2] + dp[i][j][3]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][3]) % mod;
代码:
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 1005;
const int mod = 998244353;
LL dp[maxn][maxn<<1][4];
int n,k;
void init()
{
Mst(dp,0);
dp[1][1][0] = dp[1][2][1] = dp[1][2][2] = dp[1][1][3] = 1;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int ca = 0; //d
while(cin>>n>>k)
{
init();
For(i,1,n)
{
int m = min(k,i<<1);
For(j,1,m)
{
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][0]) % mod;
dp[i+1][j+1][1] = (dp[i+1][j+1][1] + dp[i][j][0]) % mod;
dp[i+1][j+1][2] = (dp[i+1][j+1][2] + dp[i][j][0]) % mod;
dp[i+1][j+1][3] = (dp[i+1][j+1][3] + dp[i][j][0]) % mod;
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][1]) % mod;
dp[i+1][j+0][1] = (dp[i+1][j+0][1] + dp[i][j][1]) % mod;
dp[i+1][j+2][2] = (dp[i+1][j+2][2] + dp[i][j][1]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][1]) % mod;
dp[i+1][j+0][0] = (dp[i+1][j+0][0] + dp[i][j][2]) % mod;
dp[i+1][j+2][1] = (dp[i+1][j+2][1] + dp[i][j][2]) % mod;
dp[i+1][j+0][2] = (dp[i+1][j+0][2] + dp[i][j][2]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][2]) % mod;
dp[i+1][j+1][0] = (dp[i+1][j+1][0] + dp[i][j][3]) % mod;
dp[i+1][j+1][1] = (dp[i+1][j+1][1] + dp[i][j][3]) % mod;
dp[i+1][j+1][2] = (dp[i+1][j+1][2] + dp[i][j][3]) % mod;
dp[i+1][j+0][3] = (dp[i+1][j+0][3] + dp[i][j][3]) % mod;
}
}
LL ans = 0;
For(i,0,3)
ans = (ans + dp[n][k][i]) % mod;
cout<<ans<<endl;
}
return 0;
}