A. Berzerk
time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Rick and Morty are playing their own version of Berzerk (which has nothing in common with the famous Berzerk game). This game needs a huge space, so they play it with a computer.
In this game there are n objects numbered from 1 to n arranged in a circle (in clockwise order). Object number 1 is a black hole and the others are planets. There’s a monster in one of the planet. Rick and Morty don’t know on which one yet, only that he’s not initially in the black hole, but Unity will inform them before the game starts. But for now, they want to be prepared for every possible scenario.
Each one of them has a set of numbers between 1 and n - 1 (inclusive). Rick’s set is s1 with k1 elements and Morty’s is s2 with k2 elements. One of them goes first and the player changes alternatively. In each player’s turn, he should choose an arbitrary number like x from his set and the monster will move to his x-th next object from its current position (clockwise). If after his move the monster gets to the black hole he wins.
Your task is that for each of monster’s initial positions and who plays first determine if the starter wins, loses, or the game will stuck in an infinite loop. In case when player can lose or make game infinity, it more profitable to choose infinity game.
Input
The first line of input contains a single integer n (2 ≤ n ≤ 7000) — number of objects in game.
The second line contains integer k1 followed by k1 distinct integers s1, 1, s1, 2, …, s1, k1 — Rick’s set.
The third line contains integer k2 followed by k2 distinct integers s2, 1, s2, 2, …, s2, k2 — Morty’s set
1 ≤ ki ≤ n - 1 and 1 ≤ si, 1, si, 2, …, si, ki ≤ n - 1 for 1 ≤ i ≤ 2.
Output
In the first line print n - 1 words separated by spaces where i-th word is “Win” (without quotations) if in the scenario that Rick plays first and monster is initially in object number i + 1 he wins, “Lose” if he loses and “Loop” if the game will never end.
Similarly, in the second line print n - 1 words separated by spaces where i-th word is “Win” (without quotations) if in the scenario that Morty plays first and monster is initially in object number i + 1 he wins, “Lose” if he loses and “Loop” if the game will never end.
Examples
input
5
2 3 2
3 1 2 3
output
Lose Win Win Loop
Loop Win Win Win
input
8
4 6 2 3 4
2 3 6
output
Win Win Win Win Win Win Win
Lose Win Lose Lose Win Lose Lose
这次CF的赛题的故事背景是我最爱的RICK AND MORTY,结果还是A不动题目,对不起他们= =。
题目大意:一个环形路径编号为1-n,1号点为黑洞,玩家轮流让怪物前进若干步(从自己的操作集合里随便选),若该轮怪物走到黑洞,则该轮的玩家胜利。简单来说,当怪物在x点时,轮到玩家a操作,他有个操作为前进y步,若前进y步之后刚好到达1号点,则怪物死亡,玩家a胜利。题目要求我们求出所以怪物初始位置和玩家ab各自先手的游戏结果。
设状态dp[x][y]表示当前怪物在x点,轮到玩家y操作的游戏结果。所以dp[1][0]和dp[1][1]的结果都是失败,若在dp[x][y]的情况下,玩家的任意操作到达的dp[x’][y’]的状态是y’玩家失败,则dp[x][y]为胜利(玩家选择该操作即可胜利),反之,若玩家的所有选择到达的下一个状态dp[x’][y’]都是另一个玩家y’胜利,则dp[x][y]为失败的,搜索就行。
不过因为会有陷入循环的loop的结果,所以递推不大好实现,我选择了使用逆向bfs的方法,有点像拓扑排序(先初始化所有点的度数为可操作数),先让点[0][0]和[0][1]入队,对于任意当前队列头的点,如果这个点的状态是失败,则逆推出能从哪些点到这一点,那些点的状态都是胜利并且入队;如果这个点的状态是失败,则让所有逆推出来的上一步的点的度数减一,如果该点的度数为0,则该点的状态是失败并且入队。最后那些始终没有入队过的就是陷入循环的点了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int mod = 1000000007;
const int maxm = 50000005;
const int maxn = 7005;
const int M = 25;
int n, m;
int dp[maxn][2];//存结果
int sta[2][maxn];//存操作
int k[2];
bool vis[maxn][2];//存访问
int deg[maxn][2];//存度数
struct point{
int p, turn, ans;
};
queue que;
void bfs(){
while (!que.empty()){
point cnt=que.front(); que.pop();
vis[cnt.p][cnt.turn] = 1;
int turn = !cnt.turn;
if (cnt.ans == 2){
for (int i = 0; i < k[turn]; i++){
int nex = (cnt.p + n - sta[turn][i])%n;
if (!vis[nex][turn]){ dp[nex][turn] = 1; que.push({nex,turn,1}); }
}
}
else{
for (int i = 0; i < k[turn]; i++){
int nex = (cnt.p + n - sta[turn][i]) % n;
deg[nex][turn]--;
if (deg[nex][turn] == 0&&!vis[nex][turn]){
dp[nex][turn] = 2;
que.push({ nex, turn, 2 });
}
}
}
}
}
int main() {
scanf("%d", &n);
scanf("%d", &k[0]);
for (int i = 0; i < k[0]; i++){
scanf("%d", &sta[0][i]);
}
scanf("%d", &k[1]);
for (int i = 0; i < k[1]; i++){
scanf("%d", &sta[1][i]);
}
for (int i = 0; i < n; i++){
deg[i][0] = k[0];
deg[i][1] = k[1];
}
dp[0][0] = dp[0][1] = 2;
vis[0][0] = vis[0][1] = 1;
que.push({ 0, 0 ,2});
que.push({ 0, 1 ,2});
bfs();
for (int k = 0; k <= 1; k++){
for (int i = 1; i < n; i++){
if (!vis[i][k])printf("Loop ");
else if (dp[i][k] == 1){ printf("Win "); }
else printf("Lose ");
}
printf("\n");
}
return 0;
}