题目链接:https://vjudge.net/problem/UVA-10561

题意:

两个人玩游戏,轮流操作:每次往里面添加一个X,第一个得到XXX的获胜。

题解:

详情请看《训练指南》P139,以及代码注释。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e3+; int SG[MAXN], vis[MAXN];
bool hav[MAXN]; //是否有‘X' void getSG() //SG[Len]:'.'连续长度为Len时,往其中放一个'X'的游戏的SG值。
{
SG[] = ; //长度为0时,没有后继状态,故SG[0] = mex{} = 0;
//长度为1、2、3时的后继状态为0, 故SG[1/2/3] = mex{SG[0]} = 1,之所以单独拿出来,是因为
//他们的求法与后面的不一样。
SG[] = SG[] = SG[] = ;
for(int Len = ; Len<MAXN; Len++)
{
memset(vis, , sizeof(vis));
for(int pos = ; pos<=(Len+)/; pos++)
{
//当放了一个'X'进去之后,原先的游戏因为禁区的出现而可能被分为两个子游戏。
int val = SG[Len-pos-];
if(pos>) val ^= SG[pos-];
vis[val] = ;
}
for(int j = ;;j++) if(!vis[j]){
SG[Len] = j;
break;
}
}
} int len, ans[MAXN];
bool oneHit(int pos) //判断在pos位置能否放置一个X然后赢得游戏
{
if(hav[pos]) return ;
if(pos<=len-&&hav[pos+]&&hav[pos+]) return ;
if(pos>=&&hav[pos-]&&hav[pos-]) return ;
if(pos!=&&pos!=len&&hav[pos-]&&hav[pos+]) return ;
return ;
} bool prohibit(int pos) //判断pos是否在禁区之内
{
return hav[pos]||(pos>=&&hav[pos-])||(pos>=&&hav[pos-])||
(pos<=len-&&hav[pos+])||(pos<=len-&&hav[pos+]);
} int getVAL() //得到整个游戏的SG异或和
{
int val = , L = ;
for(int i = ; i<=len; i++)
{
if(prohibit(i)) val ^= SG[L], L = ;
else L++;
}
val ^= SG[L];
return val;
} void solve()
{
ans[] = ;
for(int i = ; i<=len; i++) if(oneHit(i)) { //首先判断先手是否能“一击毙命”
ans[++ans[]] = i;
for(++i; i<=len; i++)
if(oneHit(i)) ans[++ans[]] = i;
return;
}
if(getVAL()) //否则,则利用SG来判断输赢
{
for(int i = ; i<=len; i++) if(!prohibit(i)){
hav[i] = true; //因为先手处于必胜状态,当先手走了一步之后,就轮到后手处于必败状态。
if(!getVAL()) ans[++ans[]] = i;
hav[i] = false;
}
}
} char str[MAXN];
int main()
{
getSG();
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", str+);
len = strlen(str+);
memset(hav, , sizeof(hav));
for(int i = ; i<=len; i++)
hav[i] = (str[i]=='X'); solve();
if(!ans[])
printf("LOSING\n\n");
else
{
printf("WINNING\n");
for(int i = ; i<ans[]; i++)
printf("%d ", ans[i]);
printf("%d\n", ans[ans[]]);
}
}
}

UVA10561 Treblecross —— SG博弈的更多相关文章

  1. UVA12293 Box Game —— SG博弈

    题目链接:https://vjudge.net/problem/UVA-12293 题意: 两人玩游戏,有两个盒子,开始时第一个盒子装了n个球, 第二个盒子装了一个球.每次操作都将刷量少的盒子的球倒掉 ...

  2. UVA1482 Playing With Stones —— SG博弈

    题目链接:https://vjudge.net/problem/UVA-1482 题意: 有n堆石子, 每堆石子有ai(ai<=1e18).两个人轮流取石子,要求每次只能从一堆石子中抽取不多于一 ...

  3. HDU 1848(sg博弈) Fibonacci again and again

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  4. UVA10561 Treblecross 组合游戏/SG定理

    Treblecross is a two player gamewhere the goal is to get three X in a row on a one-dimensional board ...

  5. UVA 10561 - Treblecross(博弈SG函数)

    UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',能够在'.'的位置放X.谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每一个串要是上面有 ...

  6. uva10561 - Treblecross

    Treblecross is a two player game where the goal is to get three `X' in a row on a one-dimensional bo ...

  7. hdu 1851(A Simple Game)(sg博弈)

    A Simple Game Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Tot ...

  8. HDU 1536 S-Nim SG博弈

    S-Nim Problem Description   Arthur and his sister Caroll have been playing a game called Nim for som ...

  9. POJ 3710 Christmas Game#经典图SG博弈

    http://poj.org/problem?id=3710 (说实话对于Tarjan算法在搞图论的时候就没搞太懂,以后得找时间深入了解) (以下有关无向图删边游戏的资料来自论文贾志豪<组合游戏 ...

随机推荐

  1. 洛谷——P2404 自然数的拆分问题

    题目背景 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 题目描述 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 输入输出格式 输入格式: 输入:待拆分的自然数n ...

  2. spring security 单一账户多地方登陆提醒, ajax 拦截器 Interceptor

    spring-security.xml部分代码: <http auto-config="false" > <access-denied-handler ref=& ...

  3. Mybatis原理分析一 从JDBC到Mybaits

    1.引言 本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybaits这样一个持久层框架.再而论述Mybatis作为一个数据持久层框架本身有待改进之处. 2 ...

  4. jsp网页在浏览器中不显示图片_eclipse环境下配置tomcat中jsp项目的虚拟路径

    遇到的问题是这种,在jsp网页中嵌入了本地的图片,由于会用到上传到服务器的图片,所以没有放到项目里面,而是把全部图片单独放到一个文件夹里,然后打算使用绝对路径把要显示的图片显示出来.比方是放在了E盘的 ...

  5. javascript 判断字符串是否包换字符串

    用"ghiahgiahgia".indexOf("hg"); 返回值>=0为包含,否则就是-1(不包含)

  6. vue2.0 + vux (四)Home页

    1.综合页(首页) Home.vue <!-- 首页 --> <template> <div> <!-- 顶部 标题栏 --> <app-head ...

  7. 用Camshift算法对指定目标进行跟踪

    原理 Camshift算法是Continuously Adaptive Mean Shift algorithm的简称. 它是一个基于MeanSift的改进算法.它首次由Gary R.Bradski等 ...

  8. 笔记03 wpf 在MVVM模式下怎样在Viewmodel里面获得view的控件对象

     转自http://blog.csdn.net/qing2005/article/details/6601199http://blog.csdn.net/qing2005/article/detail ...

  9. systemd、upstart和system V

    http://blog.csdn.net/kumu_linux/article/details/7653802  systemd是Linux下的一种init软件,由Lennart Poettering ...

  10. bash 的环境配置文件

    http://www.cnblogs.com/ggjucheng/archive/2012/11/01/2750179.html bash 的环境配置文件 你是否会觉得奇怪,怎么我们什么动作都没有进行 ...