Educational Codeforces Round 51 (Rated for Div. 2) D - Bicolorings (状压dp)

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/82851792

原题地址:http://codeforces.com/contest/1051/problem/D

题意:对 2 × n 2×n 格子着色,仅能着黑色或白色,问色块数为 k k 的着色方案有多少种。色块定义如下,若两个格子颜色相同且相邻,则属于同一色块;若两个格子颜色相同且所属色块相邻,则属于同一色块;否则属于不同色块。

思路:这题的矩阵很有特点,是 2 × n 2×n ,那么就可以很容易的想到是利用状态压缩来进行转移.我们设 d p [ i ] [ j ] [ k ] dp[i][j][k] 表示前 i i 列,第 i i 列的状态是 j j ,色块数为 k k 的方案数

那么对于每一个 d p [ i ] [ j ] [ k ] dp[i][j][k] 都可以由四种状态得来.所以只需要枚举列数和色块数,然后每次转移16次就行了.
具体转移参考代码

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
ll dp[1005][10][2005];//表示前i列,第i列的状态是j,色块数为k的方案数
int n, k;
int main() {
    scanf("%d%d", &n, &k);
    dp[1][0][1] = 1;
    dp[1][1][2] = 1;
    dp[1][2][2] = 1;
    dp[1][3][1] = 1;
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <=  k; j++) {
            dp[i][0][j] += dp[i - 1][0][j];
            dp[i][0][j] += dp[i - 1][1][j];
            dp[i][0][j] += dp[i - 1][2][j];
            dp[i][0][j] += dp[i - 1][3][j - 1];
            dp[i][1][j] += dp[i - 1][0][j - 1];
            dp[i][1][j] += dp[i - 1][1][j];
            if(j!=1)dp[i][1][j] += dp[i - 1][2][j - 2];
            dp[i][1][j] += dp[i - 1][3][j - 1];
            dp[i][2][j] += dp[i - 1][0][j - 1];
            if(j!=1)dp[i][2][j] += dp[i - 1][1][j - 2];
            dp[i][2][j] += dp[i - 1][2][j];
            dp[i][2][j] += dp[i - 1][3][j - 1];
            dp[i][3][j] += dp[i - 1][0][j - 1];
            dp[i][3][j] += dp[i - 1][1][j];
            dp[i][3][j] += dp[i - 1][2][j];
            dp[i][3][j] += dp[i - 1][3][j];
            for (int k = 0; k < 4; k++) dp[i][k][j] %= mod;
        }
    }
    ll ans = 0;
    for (int i = 0; i < 4; i++) ans += dp[n][i][k];
    ans %= mod;
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/82851792