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;
}