CodeForces - 1051D Bicolorings(dp) 解题报告 Apare_xzc

CodeForces - 1051D Bicolorings(dp) 解题报告

xzc 2019/3/30


vjudge链接

codeforces链接


题意:
给一个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


思路:

  1. 肯定是dp
  2. 我们下面来定义状态,对于某一列:
    黑黑(BB) 为状态0
    黑白(BW) 为状态1
    白黑(WB) 为状态2
    黑白(WW) 为状态3
  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;
}
全部评论

相关推荐

专心打鱼:互联网搬运工,贴子都要偷
点赞 评论 收藏
分享
拒绝无效加班的小师弟很中意你:求职意向没有,年龄、课程冗余信息可以删掉,需要提升项目经历。排版需要修改。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务