zoukankan      html  css  js  c++  java
  • CodeForces

    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;
    }
    
  • 相关阅读:
    0X01 OWASP WebGoat Splitting
    subprocess
    Python中getopt()函数的使用
    Python3_UDP客户端
    Python3编写TCP客户端
    Python3---pymysql库____操作数据库
    review——database (1)CH8-Relational Database Design
    删除的review——数据库 (1)CH6关系数据理论
    review——C# (15)转换
    review——C# (14)接口
  • 原文地址:https://www.cnblogs.com/Apare-xzc/p/12243664.html
Copyright © 2011-2022 走看看