Codeforces 786A Berzerk 题解 [ 绿 ] [ 有向图博弈论 ] [ BFS ]
Berzerk:有向图博弈论板子。
注意到怪物位置的状态数很少,于是考虑图论建模。因为有两个人轮流操作,所以需要建成分层图的形式,每次顺时针移动 \(x\) 的位置相当于向另一层连边。当走到任意一层编号为 \(1\) 的点或走到出度为 \(0\) 的点的时候,先手必败。
这就成一个很典的有向图博弈论问题了,直接建反图,从终止状态的胜负情况拓展到所有状态的胜负情况即可。具体地:
- 当一个点的出点有先手必败点时,该点先手必胜。
- 当一个点的出点全是先手必胜点时,该点先手必败。
- 否则,该点为平局点。
从终止状态 BFS 即可,途中记录每个点的度数,以便对第二种情况进行判断。注意不能显式建图,空间会炸掉。
时间复杂度 \(O(m)\),其中 \(m = n^2\),因为本题的 BFS 复杂度和边数有关。
#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi = pair<int, int>;
const int N = 7005;
int n, na, a[N], nb, b[N], du[2][N], st[2][N];
queue<pi> q;
int main()
{
//freopen("sample.in", "r", stdin);
//freopen("sample.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
cin >> na;
for(int i = 1; i <= na; i++) cin >> a[i];
cin >> nb;
for(int i = 1; i <= nb; i++) cin >> b[i];
for(int i = 1; i <= n; i++)
{
du[0][i] = na;
du[1][i] = nb;
}
st[0][1] = st[1][1] = -1;
q.push({0, 1});
q.push({1, 1});
while(!q.empty())
{
pi cur = q.front();
q.pop();
int u = cur.se, lv = cur.fi;
if(lv == 0)
{
for(int i = 1; i <= nb; i++)
{
int v = u - b[i];
if(v <= 0) v += n;
if(st[lv ^ 1][v]) continue;
if(st[lv][u] == -1)
{
st[lv ^ 1][v] = 1;
q.push({lv ^ 1, v});
}
else
{
du[lv ^ 1][v]--;
if(du[lv ^ 1][v] == 0)
{
st[lv ^ 1][v] = -1;
q.push({lv ^ 1, v});
}
}
}
}
else
{
for(int i = 1; i <= na; i++)
{
int v = u - a[i];
if(v <= 0) v += n;
if(st[lv ^ 1][v]) continue;
if(st[lv][u] == -1)
{
st[lv ^ 1][v] = 1;
q.push({lv ^ 1, v});
}
else
{
du[lv ^ 1][v]--;
if(du[lv ^ 1][v] == 0)
{
st[lv ^ 1][v] = -1;
q.push({lv ^ 1, v});
}
}
}
}
}
for(int i = 2; i <= n; i++)
{
if(st[0][i] == 0) cout << "Loop ";
else if(st[0][i] == 1) cout << "Win ";
else cout << "Lose ";
}
cout << "\n";
for(int i = 2; i <= n; i++)
{
if(st[1][i] == 0) cout << "Loop ";
else if(st[1][i] == 1) cout << "Win ";
else cout << "Lose ";
}
return 0;
}

浙公网安备 33010602011771号