1. 程式人生 > >Educational Codeforces Round 51 (Rated for Div. 2) D

Educational Codeforces Round 51 (Rated for Div. 2) D

題意:對2×n2×n格子著色,僅能著黑色或白色,問色塊數為kk的著色方案有多少種。色塊定義如下,若兩個格子顏色相同且相鄰,則屬於同一色塊;若兩個格子顏色相同且所屬色塊相鄰,則屬於同一色塊;否則屬於不同色塊。

思路:這題的矩陣很有特點,是2×n2×n,那麼就可以很容易的想到是利用狀態壓縮來進行轉移.我們設dp[i][j][k]dp[i][j][k]表示前ii列,第ii列的狀態是jj,色塊數為kk的方案數 那麼對於每一個dp[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; }