CodeForces - 1051D Bicolorings(dp) 解题报告 Apare_xzc
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
先挂一下zyf巨巨简短的代码
//E. Bicolorings CodeForces - 1051D
//from zyf
#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <cctype>
#include <ctime>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
using std::cin;
using std::cout;
using std::deque;
using std::endl;
using std::fill;
using std::lower_bound;
using std::pair;
using std::priority_queue;
using std::queue;
using std::set;
using std::sort;
using std::stack;
using std::string;
using std::upper_bound;
using std::vector;
const int maxn = 1000;
const long long mod = 998244353LL;
long long dp[maxn + 10][2 * maxn + 10][4];//dp[i][j][k]:n=i,components=j,last block status=k
const int mat[4][4] =
{
0,0,0,1,
1,0,2,1,
1,2,0,1,
1,0,0,0
};
void solve()
{
dp[1][1][0] = 1;
dp[1][2][1] = 1;
dp[1][2][2] = 1;
dp[1][1][3] = 1;
for (int i = 1; i < maxn; i++)
for (int j = 1; j <= 2 * i; j++)
for (int k1 = 0; k1 < 4; k1++)
for (int k2 = 0; k2 < 4; k2++)
{
dp[i + 1][j + mat[k2][k1]][k2] += dp[i][j][k1];
dp[i + 1][j + mat[k2][k1]][k2] %= mod;
}
}
int main(int argc, char **argv)
{
if (argc == 2 && strcmp(argv[1], "-debug") == 0)
{
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
}
int n, k;
cin >> n >> k;
solve();
long long ans = 0;
for (int i = 0; i < 4; i++)
ans += dp[n][k][i];
cout << ans % mod;
return 0;
}
tql
思路:
- 肯定是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;
}