1. 程式人生 > 其它 >AtCoder Beginner Contest 244 E - King Bombee(動態規劃)

AtCoder Beginner Contest 244 E - King Bombee(動態規劃)

原題連線:https://atcoder.jp/contests/abc244/tasks/abc244_e
官方題解:https://atcoder.jp/contests/abc244/editorial/3619

題意

簡單無向圖,n個點,m條邊。從S到T經過K條邊,X出現的數量是偶數,一共有多少種方案

思路

  • 先不考慮x出現的數量為偶數這個條件,用動態規劃
    狀態表示:f[i][j]表示從S到j經過i條邊的所有方案的數量
    狀態劃分:f[i + 1][j] += f[i][k], k是所有j能到的點
    初始化:f[0][S] = 1
    答案:f[K][T]

  • 考慮x為偶數這個條件,多了一個限制,狀態就要多一維
    狀態表示:f[i][j][x]

    表示從S到j經過i條邊,並且經過X的次數模2的餘數為x的所有方案的數量
    狀態劃分:1. 當j不為X時,f[i + 1][j][x] += f[i][k][x], k是所有j能到的點 2. 當j為X時,f[i + 1][j][x] += f[i][k][(x+1)%2]
    初始化:f[0][S][0] = 1
    答案:f[K][T][0]

程式碼

#include <iostream>
#include <cstring>

using namespace std;
typedef long long LL;

const int N = 2010, M = N * 2;
LL mod = 998244353;
int h[N], e[M], ne[M], idx;
LL f[N][N][2];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

int main()
{
    int n, m, k, S, T, X;
    cin >> n >> m >> k >> S >> T >> X;
    memset(h, -1, sizeof h);
    
    while (m -- )
    {
        int u, v;
        cin >> u >> v;
        add(u, v);
        add(v, u);
    }
    
    f[0][S][0] = 1;
    for(int i = 0; i <= k; i ++ )
        for(int j = 1; j <= n; j ++ )
            for(int x = 0; x < 2; x ++ )
            {
                for(int u = h[j]; ~u; u = ne[u])
                {
                    int k = e[u];
                    if(j != X)  f[i + 1][j][x] = ((LL)f[i + 1][j][x] + f[i][k][x]) % mod;
                    else    f[i + 1][j][x] = ((LL)f[i + 1][j][x] + f[i][k][(x + 1) % 2]) % mod;
                }
            }
    cout << f[k][T][0];
    return 0;
}