uva 10561 sg定理
Problem C Treblecross Input: Standard Input
Output: Standard Output
Time Limit: 4 Seconds
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 Output for 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出现,则该玩家获得胜利。
你的任务是判断先手必胜还是必败,若必胜则,输出所有毕生策略(第一步)。
分析:
遍历每个能操作的位置
(1)若先手走一步后已出现3个连续的X,则此操作为必胜策略。
(2)不能一步定胜负的情况。先手选择一步后,遍历后手的操作。
1:若后手一步能达到3个连续的X,则先手的操作不是必胜策略。
2:第一个操作跟第二个操作都不能判定胜负,求sg函数。
一段全是空白的格子,把X放在任意一个位置,它的右边两个格子跟左边的两个格子(存在的格子)谁去放谁输。每位选手都是用最优的策略,所以X附近的这几个为禁区,拆分为子游戏的时候属于禁区的格子直接不要。
整个游戏,可以看成若干子游戏。g(x)=mex{g(x-3),g(x-4),g(x-5),g(1) xor g(x-6),g(2) xor g(x-7).....}
AC代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std; vector<int> v;
int sg[]; int Max(int a,int b)
{
return a>b?a:b;
} int mex(int n)
{
bool flag[];
int i,t;
if(sg[n]!=-) return sg[n];
if(n==) return sg[n]=;
memset(flag,false,sizeof(flag));
//i位置放X,它左边两个跟右边两个都为禁区,谁再放X谁输
for(i=;i<=n;i++)
{
//一个游戏分成两个子游戏
t=(mex(Max(,i-))^mex(Max(,n-i-)));
flag[t]=true;
}
for(i=;i<;i++)
if(!flag[i]) break;
return sg[n]=i;
}
bool is_oi(string s) //判断先手是否已经胜利
{
for(int i=;i<s.size()-;i++)
if(s[i]=='X' && s[i+]=='X' && s[i+]=='X')
return true;
return false;
} bool is_oi1(string s) //先手一步后,不能确认先手胜利的情况
{
int i;
for(i=;i<s.size();i++)//后手一步后,若后手必胜了,就没判断的必要了
{
if(s[i]=='.')
{
s[i]='X';
if(is_oi(s)) return false;
s[i]='.';
}
}
int ans=;//整个游戏的SG值
int num=;//子游戏的格子个数
for(i=;i<s.size();i++)//找子游戏(子游戏的定义:一段空白格子两端端点以外的X不影响游戏的结果)
{
//X的前两个空格跟后两个空格都不是最优的走法(必败),所以子游戏(两个X之间一段空白的格子减去每个X附近的两个格子数)
if(s[i]=='X'||(i>=&&s[i-]=='X')||(i>=&&s[i-]=='X')||(i+<s.size()&&s[i+]=='X')||(i+<s.size()&&s[i+]=='X'))
{ans^=mex(num);num=;}
else num++;
}
ans^=mex(num);
if(ans==)
return true;
return false;
} void solve(string s)
{
for(int i=;i<s.size();i++)//先手走一步后,看后手的状态
{
if(s[i]=='.')
{
s[i]='X';
if(is_oi(s) || is_oi1(s)) //如果先手这一步,后手的状态是必败的,记录位置
v.push_back(i+);
s[i]='.';
}
}
} int main()
{
memset(sg,-,sizeof(sg));
int t;
string s;
cin>>t;
while(t--)
{
v.clear();
cin>>s;
solve(s);
if(v.size()==) //先手没有必胜的情况,肯定必败。
cout<<"LOSING"<<endl<<endl;
else
{
cout<<"WINNING"<<endl;
for(int i=;i<v.size();i++)
printf(i?" %d":"%d",v[i]);
cout<<endl;
}
}
return ;
}
uva 10561 sg定理的更多相关文章
- UVa 10561 (SG函数 递推) Treblecross
如果已经有三个相邻的X,则先手已经输了. 如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜. 除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,对手下一轮再放一个就输了. 最后当“ ...
- UVA 10561 - Treblecross(博弈SG函数)
UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',能够在'.'的位置放X.谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每一个串要是上面有 ...
- HDU5795A Simple Nim SG定理
A Simple Nim Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- HDU5724 Chess(SG定理)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5724 Description Alice and Bob are playing a spe ...
- HDU 1851 (巴什博奕 SG定理) A Simple Game
这是由n个巴什博奕的游戏合成的组合游戏. 对于一个有m个石子,每次至多取l个的巴什博奕,这个状态的SG函数值为m % (l + 1). 然后根据SG定理,合成游戏的SG函数就是各个子游戏SG函数值的异 ...
- SG函数和SG定理【详解】
在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点 ...
- 简单易懂的博弈论讲解(巴什博弈、尼姆博弈、威佐夫博弈、斐波那契博弈、SG定理)
博弈论入门: 巴什博弈: 两个顶尖聪明的人在玩游戏,有一堆$n$个石子,每次每个人能取$[1,m]$个石子,不能拿的人输,请问先手与后手谁必败? 我们分类讨论一下这个问题: 当$n\le m$时,这时 ...
- 【bzoj3576】[Hnoi2014]江南乐 博弈论+SG定理+数学
题目描述 两人进行 $T$ 轮游戏,给定参数 $F$ ,每轮给出 $N$ 堆石子,先手和后手轮流选择石子数大于等于 $F$ 的一堆,将其分成任意(大于1)堆,使得这些堆中石子数最多的和最少的相差不超过 ...
- SG函数&&SG定理
必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的 ...
随机推荐
- 精仿百思不得姐客户端应用iOS源码
XFBaiSiBuDeJie 高仿百思不得姐客户端 初次学习使用RAC,还不是怎么熟悉,使用的仍是MVC模式,MVVM还在摸索中... 如果大家觉得还不错,请给颗星星支持下~~~ 程序中使用到的库 A ...
- ABAP Netweaver, SAP Cloud Platform和Kubernetes的用户区分
ABAP Dialog: Individual, interactive system access. System: Background processing and communication ...
- Makefile入门教程
Makefile介绍 make是一个命令工具,它解释Makefile 中的指令(应该说是规则).在Makefile文件中描述了整个工程所有文件的编译顺序.编译规则.Makefile 有自己的书写格式. ...
- linux 用dd命令读写引导区文件
分类: LINUX 备份MBR,linux下使用如下命令: # dd if=/dev/hda of=/root/linux.bin bs=512 count=1 这里注意使用if=/dev/hda备份 ...
- Sql语句的一些事(一)
(1)LIMIT子句(MySql) ----LIMIT 子句用于规定要返回的记录的数目,一般和Order By一起使用 经常用于数据的分页查询,但是一旦数据量一大,limit的性能就会急速下降 格式: ...
- scrollTop如何实现click后页面过渡滚动到顶部
用JS操作,body元素的scrollTop var getTop = document.getElementById("get-top"); var head = documen ...
- 《零基础入门学习Python》【第一版】视频课后答案第006讲
python中被看作假:FALSE none 0 ‘ ’ " " ( ) [ ] { },其他一切都被解释为真 测试题答案: 0.Python 的 floor 除法现在使用 ...
- 刚毕业去面试Python工程师,这几道题太难了,Python面试题No11
写在前面 本想停一段时间这个系列,但是好多朋友给我发信息说让我继续整理下去,so,继续吧~ 第1题: docstring是什么? docstring是一种文档字符串,用于解释构造的作用.我们在函数.类 ...
- python--前端CSS
一.CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义了如何显示HTML元素,给HTML设置样式,让他更加美观. 当浏览器读到这个样式表, 他就会按照这个样式来对文档进行 ...
- Day08字符编码
Day08: 知识储备: 硬盘:由硬盘加载到内存,cpu从内存中取 软件产生的数据都是先保存在内存中 文件,输入文字,保存到内存,内存是硬件,硬件只能保存2进制,所以需要转换 文本编辑器,输入文字的时 ...