uva 10561 Treblecross (SG函数)

来源:互联网 发布:心理咨询师三级网络课 编辑:程序博客网 时间:2024/05/29 03:59

uva 10561 Treblecross (SG函数) :http://acm.hust.edu.cn/vjudge/contest/view.action?cid=113567#problem/A 传送门:nefu

题面:

Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu
Submit Status

Description

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

Given the current state of the game, you are to determine if the current player to move can win the game assuming both players play optimally.

Consider the game where the board size is 5 cells. If the first player puts an X at position three (in the middle) so the state becomes ..X.., he will win the game as no matter where the other player puts 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 win the game by putting the X in the opposite corner (for instance, after the second players move the state might be .X..X). This will force the first player to put an X in a position so the second player wins in the next move.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing a string denoting the current status of the game. The string will only contain the characters '.' and 'X'. The length of the string (the size of the board) will be between 3 and 200 characters, inclusive. No state will contain three X in a row.

Output

For each case, print the case number and the positions on the board, where the player to move may put an X and win the game. The positions should be separated by a single space, and be in increasing order. The leftmost position on the board is 1. If there is no such position print 0.

Sample Input

4

.....

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

.X.X...X

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

Sample Output

Case 1: 3

Case 2: 0

Case 3: 3

Case 4: 5 6 13 14

题目大意:

在一个一维的线性结构棋盘上两人先后分别放置X,先使得三个X直接相连者获胜,已知现在棋盘状态为已知态,且假设两个玩家都玩此游戏玩得比较6,如果先手能赢,则按升序输出先手所有需要放置X的位置,下标从1开始,否则输出0。

算法分析及解释:

已知结论:如果当前节点为'X',则在有选择的情况下,我们绝对不会向当前节点的两边的附近两个位置处放置'X',即此四个位置为“禁区”,则整个棋盘被分成多个部分,由于数据比较小,我们可以枚举每个位置的必胜必败情况。


代码实现:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;int sg[210];int vis[210];void getsg() ///根据题目要求状态计算SG函数{    int i,j,k;    sg[0]=0;    sg[1]=sg[2]=sg[3]=1;    for( i=4;i<=200;i++)    {        memset(vis,0,sizeof(vis));        for(j=3;j<=5&&i-j>=0;j++)            vis[sg[i-j]]=1;        for(j=6;i-j>=0;j++)            vis[sg[j-5]^sg[i-j]]=1;        for(j=max(i-5,0);j<=i-3;j++)            vis[sg[j]]=1;        for(j=0;j<=200;j++)        {            if(!vis[j])            {                sg[i]=j;                break;            }        }    }}int s[210],f[210],g[210],len;int findd(){    int ans=0;    int i,j,kk=0;    for(i=0;i<len;i++)    {        if(f[i]==0)        {            kk++;        }        else        {            ans=ans^sg[kk];            kk=0;        }    }    ans=ans^sg[kk];    return ans;}int main(){    int t,casenum=0;    char str[210];    getsg();    cin>>t;    while(t--)    {        scanf("%s",str);        len=strlen(str);        int k=0,flag=0;        memset(s,0,sizeof(s));        for(int i=0;i<len;i++)        {            if(i<=len-3&&str[i+1]=='X'&&str[i+2]=='X')            {                flag=1;                s[k++]=i;            }            else if(i>=1&&str[i-1]=='X'&&str[i+1]=='X')            {                flag=1;                s[k++]=i;            }            else if(i>=2&&str[i-1]=='X'&&str[i-2]=='X')            {                flag=1;                s[k++]=i;            }        }        if(flag)        {            printf("Case %d: ",++casenum);            cout<<s[0]+1;            for(int i=1;i<k;i++)            {                cout<<" "<<s[i]+1;            }            cout<<endl;        }        else        {            memset(g,0,sizeof(g));            for(int i=0;i<len;i++)            {                if(str[i]=='X')                {                    for(int j=i-2;j<=i+2;j++)                    {                        if(j>=0&&j<len)                        {                            g[j]=1;                        }                    }                }            }            memcpy(f,g,sizeof(f));            if(findd()==0)            {                printf("Case %d: 0\n",++casenum);                continue;            }            for(int i=0;i<len;i++)            {                if(g[i]==0)                {                    memcpy(f,g,sizeof(f));                    for(int j=i-2;j<=i+2;j++)                    {                        if(j>=0&&j<len)                        {                            f[j]=1;                        }                    }                    if(findd()==0)                    {                        s[k++]=i;                    }                }            }            printf("Case %d: ",++casenum);            cout<<s[0]+1;            for(int i=1;i<k;i++)            cout<<" "<<s[i]+1;            cout<<endl;        }    }    return 0;}




0 0
原创粉丝点击