1. 程式人生 > >【組合數學dp】Educational Codeforces Round 51 (Rated for Div. 2) D. Bicolorings

【組合數學dp】Educational Codeforces Round 51 (Rated for Div. 2) D. Bicolorings

Step1 Problem:

給你 2*n 的矩陣,你可以對於每個格子填塗黒色或者白色,如果相鄰顏色一樣看成同一塊,問你塗完後恰好有 k 塊的方案數。
資料範圍:
1 <= n <= 1000, 1 <= k <= 2n.

Step2 Ideas:

總有一股組合數學的味道。
直接說題解:
dp[i][0][k]: 恰好為 k 塊上下都黑的方案數
dp[i][1][k]: 恰好為 k 塊上黑下白的方案數
dp[i][2][k]: 恰好為 k 塊上白下黑的方案數
dp[i][3][k]: 恰好為 k 塊上下都白的方案數

Step3 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3+5;
const int MOD = 998244353;
ll dp[N][4][2*N];
int main()
{
    int n, K;
    scanf("%d %d", &n, &K);
    K = K+2;//這樣就陣列就不會訪問到負數了
    dp[1][0][1+2] = 1;
    dp[1][1][2+2] = 1;
    dp[1][2][2+2] = 1;
    dp[1][3][1+2] = 1;
    ll ans = 0;
    for(int i = 2; i <= n; i++)
    {
        for(int k = 3; k <= K; k++)
        {
            dp[i][0][k] = dp[i-1][0][k] + dp[i-1][1][k] + dp[i-1][2][k] + dp[i-1][3][k-1], dp[i][0][k] %= MOD;
            dp[i][1][k] = dp[i-1][0][k-1] + dp[i-1][1][k] + dp[i-1][2][k-2] + dp[i-1][3][k-1], dp[i][1][k] %= MOD;
            dp[i][2][k] = dp[i-1][0][k-1] + dp[i-1][1][k-2] + dp[i-1][2][k] + dp[i-1][3][k-1], dp[i][2][k] %= MOD;
            dp[i][3][k] = dp[i-1][0][k-1] + dp[i-1][1][k] + dp[i-1][2][k] + dp[i-1][3][k], dp[i][3][k] %= MOD;
        }
    }
    for(int i = 0; i < 4; i++)
        ans += dp[n][i][K];
    ans %= MOD;
    printf("%lld\n", ans);
    return 0;
}