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 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

 


Problemsetter:Jimmy M?rdell, Member of Elite Problemsetters‘ Panel

题意:有n个格子排成一行,其中一些格子里面有字符X,两个游戏者轮流操作,每次都可以选个空格,在里面放上字符X,如果此时有3个连续的X出现,则该游戏者赢得比赛

起始情况下不会有3个连续的X出现,你的任务是判断先手是必胜或者必败,必胜输出所有的策略

思路:如果输入中已经有3个连续的了,如果有可能实现三个连续的话,那么就是必胜的啦,这是可以直接判断的。还有一个比较明显的结论是:我们不会在X的附近两个放X的

,我们把这块称为“禁区”,那么整个格子就被我们分成若干个部分,设g(x)表示长度为x的所对应的SG函数值,那么我们就可以得到递推式:

g(x)=mex  
{ g(x?3),g(x?4),g(x?5),g(1)
or
g(x?6)...         
      } ,就是枚举长度x时候从后往前放X后的可能情况

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 210;

int SG[maxn];
char str[maxn], tmp[maxn];

int cal(int x) {
	if (x < 0)
		return 0;
	if (SG[x] != -1)
		return SG[x];

	int vis[maxn];
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= x; i++)
		vis[cal(i-3)^cal(x-i-2)] = 1;
	for (int i = 0; ; i++)
		if (!vis[i])
			return SG[x] = i;
}

int judge(int x) {
	if (str[x] == 'X')
		return 0;
	strcpy(tmp, str);
	tmp[x] = 'X';
	int len = strlen(str);

	for (int i = 0; i+2 < len; i++)
		if (tmp[i] == 'X' && tmp[i+1] == 'X' && tmp[i+2] == 'X')
			return 1;
	for (int i = 0; i < len; i++) {
		if (i+1 < len && tmp[i] == 'X' && tmp[i+1] == 'X')
			return 0;
		if (i+2 < len && tmp[i] == 'X' && tmp[i+2] == 'X')
			return 0;
	}

	int ans = 0,flag = 0, w = 2, cnt = -1;
	for (int i = len-1; i >= 0; i--)
		if (tmp[i] == 'X') {
			cnt = i;
			break;
		}
	for (int j, i = 0; i < len; i++) {
		if (i > cnt)
			w = 0;
		if (tmp[i] == 'X')
			flag = 2;
		if (tmp[i] != '.')
			continue;
		for (j = i; j < len && tmp[j] == '.'; j++) ;
		ans ^= cal(j-i-flag-w);
		i = j-1;
	}

	return ans == 0;
}

int main() {
	memset(SG, -1, sizeof(SG));
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%s", str);
		vector<int> ve;
		for (int i = 0; i < strlen(str); i++)
			if (judge(i))
				ve.push_back(i);

		if (ve.size()) {
			printf("WINNING\n");
			for (int i = 0; i < ve.size()-1; i++)
				printf("%d ", ve[i]+1);
			printf("%d\n", ve[ve.size()-1]+1);
		}
		else printf("LOSING\n\n");
	}
	return 0;
}

UVA - 10561 Treblecross (SG定理)

时间: 2024-12-21 22:20:09

UVA - 10561 Treblecross (SG定理)的相关文章

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(博弈论)

题目链接: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

(转载)--SG函数和SG定理【详解】

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质: 1.所有终结点是 必败点 P .(我们以此为基本前提进行推理,换句话说,我们以此为假设) 2.从任何必胜点N 操作,至少有一种方式可以进入必败点 P. 3.无论如何操作,必败点P 都只能进入 必胜点 N. 我们研究必胜点和必败点的目的时间为题进行简化,有助于

SG函数和SG定理【详解】

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质: 1.所有终结点是 必败点 P .(我们以此为基本前提进行推理,换句话说,我们以此为假设) 2.从任何必胜点N 操作,至少有一种方式可以进入必败点 P. 3.无论如何操作,必败点P 都只能进入 必胜点 N. 我们研究必胜点和必败点的目的时间为题进行简化,有助于

HDU5795A Simple Nim SG定理

A Simple Nim Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 980    Accepted Submission(s): 573 Problem Description Two players take turns picking candies from n heaps,the player who picks the l

组合游戏 - SG函数和SG定理

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质: 1.所有终结点是 必败点 P .(我们以此为基本前提进行推理,换句话说,我们以此为假设) 2.从任何必胜点N 操作,至少有一种方式可以进入必败点 P. 3.无论如何操作,必败点P 都只能进入 必胜点 N. 我们研究必胜点和必败点的目的时间为题进行简化,有助于

HDU 1851 (巴什博奕 SG定理) A Simple Game

这是由n个巴什博奕的游戏合成的组合游戏. 对于一个有m个石子,每次至多取l个的巴什博奕,这个状态的SG函数值为m % (l + 1). 然后根据SG定理,合成游戏的SG函数就是各个子游戏SG函数值的异或和. 1 #include <cstdio> 2 3 int main() 4 { 5 int T, n; scanf("%d", &T); 6 while(T--) 7 { 8 scanf("%d", &n); 9 int s = 0,