uva10561 - Treblecross SG定理

来源:互联网 发布:数码宝贝2知乎 编辑:程序博客网 时间:2024/06/06 12:36

Treblecross
Input:
Standard Input

Output: Standard Output

Time Limit: 4 Seconds

 

Treblecross is a two player gamewhere the goal is to get three X in a row on a one-dimensional board. At the startof the game all cells in the board is empty. In each turn a player puts a X in an empty cell, and if that results in there beingthree X next to each other, that player wins.

Given the current state of the game, you are todetermine if the player to move can win the game assuming both players playperfectly. If so, you should also print all moves that will eventually lead toa win.

Consider the game where the board size is 5cells. If the first player puts a X at position three (in the middle) so thestate becomes ..X.., he will win the game as no matter where the other playerputs his X, the first player can get three X in a row. If, on the other hand,the first player puts the X in any other position, the second player will winthe game by putting the X in the opposite corner (for instance, after thesecond player moves the state might be .X..X). This will force the first playerto put an X in a position so the second player wins in the next move.

Input

The input begins with an integer N (N<100),the number of states that will follow. Each state is represented by a string ona line by itself. The string will only contain the characters '.' and 'X'. Thelength of the string (the size of the board) will be between 3 and 200characters, inclusive. No state will contain three X in a row.

 

Output

For each case, first output WINNING or LOSING depending onif the player to move will win or lose the game. On the next line, output inincreasing order all positions on the board where the player to move may put anX and win the game. The positions should be separated by a blank, and be inincreasing order. The leftmost position on the board is 1.

 

SampleInput                                             Outputfor Sample Input

4

.....

X.....X..X.............X....X..X

.X.X...X

...............................................

 

WINNING

3

LOSING

 

WINNING

3

WINNING

1 12 15 17 20 24 28 31 33 36 47

 

  N个格子排成一行,里面有些是X,两个人轮流往空的地方放X,如果出现连续3个X,那个人获胜,。如果能获胜,输出必胜方案的第一步。

  我最开始想的是递归子状态的SG,可能是因为X位置问题,不能表示状态。。

  其实完全可以先求出所有地方都是空的SG,sg[n]表示连续连续n个空的SG值。那样对于某种状态,只要在把它能放X的段的SG全部异或就行了。

#include<iostream>#include<queue>#include<cstring>#include<cstdio>#include<cmath>#include<set>#include<map>#include<vector>#include<stack>#include<algorithm>#define eps 1e-9#define MAXN 210#define MAXM 110#define MOD 100000007typedef long long LL;using namespace std;int T,sg[MAXN],g[MAXN];char str[MAXN];vector<int> ans;int win(){    int L=strlen(str);    for(int i=0;i<L-2;i++) if(str[i]=='X'&&str[i+1]=='X'&&str[i+2]=='X') return 0;    int no[MAXN]={0};    for(int i=0;i<L;i++) if(str[i]=='X'){        for(int d=-2;d<=2;d++) if(i+d>=0&&i+d<L){            if(d&&str[i+d]=='X') return 1;  //1不一定表示这个状态的SG,SG有可能更大。反正这道题只要有SG大于0就可以            no[i+d]=1;        }    }    no[L]=1;    int start=-1,SG=0;    for(int i=0;i<=L;i++){        if(start<0&&!no[i]) start=i;        if(no[i]){            if(start>=0) SG^=sg[i-start];            start=-1;        }    }    return SG;}int mex(vector<int>& s){    if(s.empty()) return 0;    sort(s.begin(),s.end());    if(s[0]) return 0;    int L=s.size();    for(int i=1;i<L;i++) if(s[i]>s[i-1]+1) return s[i-1]+1;    return s[L-1]+1;}void init(){    sg[0]=0;    sg[1]=sg[2]=sg[3]=1;    for(int i=4;i<MAXN;i++){        vector<int> s;        s.push_back(sg[i-3]);        s.push_back(sg[i-4]);        if(i>=5) s.push_back(sg[i-5]);        for(int j=3;j<i-3;j++) s.push_back(sg[j-2]^sg[i-j-3]);        sg[i]=mex(s);    }}int main(){    freopen("in.txt","r",stdin);    init();    scanf("%d",&T);    while(T--){        scanf("%s",str);        ans.clear();        int sum=win();        if(!win()){            printf("LOSING\n\n");            continue;        }        for(int i=0;i<strlen(str);i++) if(str[i]=='.'){            str[i]='X';            if(!win()) ans.push_back(i+1);            str[i]='.';        }        int L=ans.size();        if(L){            printf("WINNING\n");            int first=1;            for(int i=0;i<L;i++){                if(first) first=0;                else printf(" ");                printf("%d",ans[i]);            }            puts("");        }        else printf("LOSING\n");    }    return 0;}



0 0
原创粉丝点击