Treblecross

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 is empty. In each turn a player puts a ‘X’ in an empty
cell, and if that results in there being three ‘X’ next to each other, that player wins.
Given the current state of the game, you are to determine if the player to move can win the game
assuming both players play perfectly. If so, you should also print all moves that will eventually lead to
a win.
Consider the game where the board size is 5 cells. If the first player puts a ‘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 player moves 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
The input begins with an integer N (N < 100), the number of states that will follow. Each state is
represented by a string on a line by itself. 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, first output ‘WINNING’ or ‘LOSING’ depending on if the player to move will win or lose the
game. On the next line, output in increasing order all positions on the board where the player to move
may put an X and win the game. The positions should be separated by a blank, and be in increasing
order. The leftmost position on the board is 1.
Sample Input
4
.....
X.....X..X.............X....X..X
.X.X...X
...............................................

Sample Output
WINNING
3
LOSING
WINNING
3
WINNING
1 12 15 17 20 24 28 31 33 36 47

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=210;
int t,res[maxn],way,len,sg[maxn];
char str[maxn];
bool judge(){
   for(int i=0;i<len-2;i++)
   if(str[i]==‘X‘&&str[i+1]==‘X‘&&str[i+2]==‘X‘)return true;//if have win(three_X_inline),just true
   return false;//or just return false
}
int getsg(int x){
    if(sg[x]!=-1)return sg[x];//if has work the sg out,just return
    if(x==0) return sg[x]=0;//if it‘s the first one ,just return it‘s sg as 0
    bool vis[maxn];int t;memset(vis,false,sizeof(vis));//set a visit array and initialization it
    for(int i=1;i<=x;i++){
       int t=getsg(max(0,i-3))^getsg(max(0,x-i-2));
       vis[t]=true;//get the next_sg and set it has been visited
    }
    for(int i=0;;i++){if(vis[i])continue;return sg[x]=i;}//if it has vist just go on ,or just return it and set the sg_mark as it
}
int getres(){
    for(int i=0;i<len;i++)
       if(str[i]==‘.‘){//if it is a space
            str[i]=‘X‘;//just work there(put X there)
            if (judge()){str[i]=‘.‘;return false;}//if can win,just set it back to the space and return false
            str[i]=‘.‘;//set it back
        }int ans=0,num=0;//set two variable
    for(int i=0;i<len;i++)
        if(str[i]==‘X‘||(i>=1&&str[i-1]==‘X‘)||(i>=2&&str[i-2]==‘X‘)||(i+1<len&&str[i+1]==‘X‘)||(i+2<len&&str[i+2]==‘X‘))
        //if this point is X |or|left one is X|or|the last second point is X|or|right one is X|or|the next second point is X
            ans^=getsg(num),num=0;//renew the mark,and initialization the num
        else num++;//or just renew the num
    ans^=getsg(num);return ans==0;//renew the final mark
    //if the mark is false ,just return true or just return false
}
void solve(){way=0;len=strlen(str);//initialization the mark and the lenth of the map
    for(int i=0;i<len;i++)//deal with every map_part
    {
        if(str[i]!=‘.‘)continue;//if it is not a space ,just run to next map_part
        str[i]=‘X‘;//if it is a space just work there(put X there)
        if (judge()||getres())//if can win or the mark is false just set it into the win_case and set the place back
        res[++way]=i+1;str[i]=‘.‘;
    }
}
int main(){memset(sg,-1,sizeof(sg));scanf("%d",&t);//initialization sg and read the case_num
    while(t--){
        scanf("%s",str);solve();//read the map,and initialization_operation
        if(way==0)puts("LOSING\n");//if the win_case_num is 0,just has no win_solution ,just the lose_case
        else{
            puts("WINNING");//or ,the win_case
            for(int i=1;i<=way;i++)printf("%d%c",res[i],i==way?‘\n‘:‘ ‘);//printf every win_method. if i==way printf\n or printf‘ ‘
        }
    }return 0;
}

program is just above ,the program is the best solution

时间: 2024-08-30 03:21:39

Treblecross的相关文章

Treblecross 博弈SG值

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 t

UVA 10561 - Treblecross(博弈SG函数)

UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',可以在'.'的位置放X,谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败),所以可以以X分为几个子游戏去求SG函数的异或和进行判断,至于求策略,就是枚举每个位置就可以了 代码: #include <stdio.h> #include <string.h> #include <algorithm> usi

uva 10561 - Treblecross(Nim)

题目链接:uva 10561 - Treblecross 题目大意:n个格子排成一排,其中一些格子有'X',两个游戏者轮流操作,在格子中放X,如果此时出现连续3个X,则获胜.给出先手是否可以取胜,取胜方案的第一步该怎么走. 解题思路:一个X可以导致左右两个的两个格子都不能再放X,因为如果出现XX...XX.X.X,那么下一个人肯定胜利.所以对于长度为n的格子序列,g(x)=maxg(x?3),g(x?4)...g(2)XORg(n?7). 所以可以预先处理出g数组,然后对于给定的序列,枚举先手下

UVA - 10561 Treblecross (SG定理)

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

Treblecross(uva 10561)

题意:一个 1 × n 的棋盘,有 X 和 :,当棋盘上出现三个连续的X 时游戏结束,两人轮流操作,每次能把一个 : 变成 X,问先手必胜方案数以及先手可以放的位置. /* 对于先手,当有一个'X'时,它周围的两个格子就都不能放'X'了,所以这样游戏就被分成了几个部分,据此设定SG函数. */ #include<iostream> #include<cstdio> #include<cstring> #define N 210 using namespace std;

UVA 10561 Treblecross(博弈论)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32209 [思路] 博弈论. 根据X分布划分禁区,每个可以放置的块为单独一个游戏.按长度定义状态,构造sg函数.依次试验每一种放法. [代码] 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 using names

UVA 10561 Treblecross

白书上的例题,用长度作为状态推算sg值.代码写的有点挫. #include<complex> #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; vector<int> ans; char s[300]; int g[210]; int len; int

UVa10561 Treblecross

博弈 sg函数 如果能一步取胜的话,直接扫一遍,找出所有能一步取胜的位置输出. 否则枚举放‘X’的位置,计算剩下空区间的SG函数的异或和,若为0,则该位置可以作为答案. 计算空区间时要刨去X旁边的两个空(放在这里必败) 例如.X.....X.这一区段的可用长度为3 SG函数的预处理还不太理解 ↓那个pd()并没有用到 1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring&g

UVa 10561 (SG函数 递推) Treblecross

如果已经有三个相邻的X,则先手已经输了. 如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜. 除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,队手下一轮再放一个就输了. 最后当“禁区”布满整行,不能再放X了,那个人就输了. 每放一个X,禁区会把它所在的线段“分割”开来,这若干个片段就可以看做若干个游戏的和. 设g(x)表示x个连续格子对应的SG函数值,递推来求g(x): g(x) = mex{ g(x-3), g(x-4), g(x-5), g(x-6) xor g(1),