签到题,算一下b+=a和d+=c,然后卡一下次数就可以了。
只要一组出现一对相反数就是安全的。
题意:【1,n】,两个人轮流走,谁能走到1谁就赢,求每个人先手在【2,n】时的胜负情况。
一直没怎么写过博弈论的题,但其实这种题也只是一个bfs。
必胜态:有一条边走到必败态
必败态:连出去的所有边都是必胜态。
方法:倒着bfs,把1作为必败态进队,如果当前是必败态,能到达都是必胜态,如果当前是必胜态,能到达的所有的点入度-1,如果入度减到说明一定是必败态。
#include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define rep(i,l,r) for(int i=l;i<=r;i++) #define dow(i,l,r) for(int i=r;i>=l;i--) #define maxn 10000 #include<vector> #include<queue> using namespace std; typedef struct { int x,op,v; }node; queue<node> pp; int n,tot[2],num[2][maxn],f[maxn][2],c[maxn][2]; int main() { scanf("%d",&n); rep(i,0,1) { scanf("%d",&tot[i]); rep(j,0,tot[i]-1) scanf("%d",&num[i][j]); } pp.push((node){0,1,-1}); pp.push((node){0,0,-1}); f[0][1]=-1; f[0][0]=-1; while (!pp.empty()) { node now=pp.front();pp.pop(); if (now.v==1) { rep(i,0,tot[!now.op]-1) { int x=(now.x-num[!now.op][i]+n)%n; if (!f[x][!now.op]&& ++c[x][!now.op]==tot[!now.op]) { f[x][!now.op]=-1; pp.push((node){x,!now.op,-1}); } } } else { rep(i,0,tot[!now.op]-1) { int x=(now.x-num[!now.op][i]+n)%n; if (!f[x][!now.op]) { f[x][!now.op]=1; pp.push((node){x,!now.op,1}); } } } } rep(i,1,n-1) { if (f[i][0]) printf("%s",f[i][0]==1?"Win":"Lose"); else printf("Loop"); printf("%s",i<n-1?" ":"\n"); } rep(i,1,n-1) { if (f[i][1]) printf("%s",f[i][1]==1?"Win":"Lose"); else printf("Loop"); printf("%s",i<n-1?" ":"\n"); } return 0; }