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;
}
posted @ 2022-03-25 10:02  inss!w!  阅读(39)  评论(0编辑  收藏  举报