题意:给你一串含“.”和“X”的字串,每次一个玩家可以把‘."变成“X”,谁先弄到三个XXX就赢。假如先手必赢,输出所有能必赢的第一步,否则输出0。

思路:显然如果一个X周围两格有X那么肯定能一步变成XXX,所以两个人都要避免在自己回合产生这种情况。如果一开始就存在上述情况,那么肯定是那一步。否则我遍历每一个空格看看能不能下这一步。满足我在这个空格变成“X”不会造成上述情况,然后算出nim和是否留给对手一个必败态。

设sg[x]表示长度为x的空格的sg函数,然后我遍历1~x位置变成“X”,那么空格键会被我分成两块(比如.....我在3位置下X,那么空格被我分成了左0右0两块,注意X旁边两块不能动)。

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
using namespace std;
int sg[maxn], s[maxn], ans[maxn], pos;
char str[maxn];
void getSG(){
sg[] = ;
for(int i = ; i < maxn; i++){
memset(s, , sizeof(s));
for(int j = ; j <= i; j++){
int t = ;
if(i - j - >= ) t ^= sg[i - j - ];
if(j - >= ) t ^= sg[j - ];
s[t] = ;
}
for(int j = ; j < maxn; j++){
if(!s[j]){
sg[i] = j;
break;
}
}
}
}
bool check(){
ll ret = ;
int num = , len = strlen(str);
for(int i = ; i < len; i++){
if(str[i] == 'X'){
if((i >= && str[i - ] == 'X') || (i >= && str[i - ] == 'X') || (i + < len && str[i + ] == 'X') || (i + < len && str[i + ] == 'X')){
return false;
}
if(str[i - num - ] == 'X' && i - num - >= )
num -= ;
num -= ;
if(num >= ) ret ^= sg[num];
num = ;
}
else{
num++;
}
}
if(str[len - - num] == 'X' && len - - num >= )
num -= ;
if(num >= ) ret ^= sg[num];
return ret == ;
}
void solve(){
pos = ;
int len = strlen(str);
for(int i = ; i < len; i++){
if(str[i] == '.'){
str[i] = 'X';
if(i + < len && i - >= && str[i + ] == 'X' && str[i - ] == 'X'){
ans[pos++] = i + ;
}
else if(i + < len && i + < len && str[i + ] == 'X' && str[i + ] == 'X'){
ans[pos++] = i + ;
}
else if(i - >= && i - >= && str[i - ] == 'X' && str[i - ] == 'X'){
ans[pos++] = i + ;
}
else if(check()){
ans[pos++] = i + ;
}
str[i] = '.';
}
}
}
int main(){
int T, Case = ;
getSG();
scanf("%d", &T);
while(T--){
scanf("%s", str);
solve();
printf("Case %d:", Case++);
if(pos == ) printf(" 0\n");
else{
for(int i = ; i < pos; i++){
printf(" %d", ans[i]);
}
printf("\n");
}
}
return ;
}

LightOJ 1229 Treblecross(SG函数打表 + 遍历)题解的更多相关文章

  1. hdu 2147 SG函数打表(手写也可以) 找规律

    kiki's game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 40000/1000 K (Java/Others) Total ...

  2. UPCOJ9526(SG函数打表,nim游戏异或规则)

    #include<bits/stdc++.h>using namespace std;int f[1007],SG[1007],S[1007];//f为可以选取的石头个数,SG为sg函数, ...

  3. bzoj 1228 [SDOI2009]E&D SG函数打表 找规律

    题目链接 Description 桌子上有2n 堆石子,编号为1..2n.将第2k-1 堆与第2k 堆(1 ≤ k ≤ n)为同一组.第i堆的石子个数用一个正整数Si表示.一次分割操作指的是,从桌子上 ...

  4. hdu1848(sg函数打表)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1848 题意:中文题诶- 思路:直接sg函数打表就好了 代码: #include <iostrea ...

  5. 51 nod1067 Bash游戏 V2(sg函数打表)

    1067 Bash游戏 V2 1.0 秒 131,072.0 KB 5 分 1级题   有一堆石子共有N个.A B两个人轮流拿,A先拿.每次只能拿1,3,4颗,拿到最后1颗石子的人获胜.假设A B都非 ...

  6. Educational Codeforces Round 68 (Rated for Div. 2)D(SG函数打表,找规律)

    #include<bits/stdc++.h>using namespace std;int sg[1007];int main(){ int t; cin>>t; while ...

  7. Nowcoder 挑战赛23 B 游戏 ( NIM博弈、SG函数打表 )

    题目链接 题意 : 中文题.点链接 分析 : 前置技能是 SG 函数.NIM博弈变形 每次可取石子是约数的情况下.那么就要打出 SG 函数 才可以去通过异或操作判断一个局面的胜负 打 SG 函数的时候 ...

  8. UVa 10561 Treblecross (SG函数)

    题意:给定上一行字符串,其中只有 X 和 . 并且没有连续的三个 X,两个玩家要分别在 . 上放 X,如果出现三个连续的 X,则该玩家胜利,现在问你先手胜还是败,如果是胜则输出第一步可能的位置. 析: ...

  9. lightoj 1229 - Treblecross 博弈论

    思路:SG函数 枚举先手的每一个位置是否有必胜. 1)如果出现了XXX则必胜: 2)如果出现了XX或X.X则必败: 3)否则计算后手的sg值和. 代码如下: #include<iostream& ...

随机推荐

  1. SVN版本控制系统搭建(结合http服务)

    SVN版本控制服务器搭建 Svn(subversion)是一个开源代码管理的控制系统,用来管理和存储开发的源代码,基于C/S模式.可以单独提供服务,也可以结合http服务来实现. 运行方式  运行端口 ...

  2. CentOS 6 网络设置

    系统配置: 系统硬件:vmware workstation 系统版本:Centos-6.6-x86_64 路由器网关:192.168.1.1 linux系统网络设置须知: 1.主机所有网卡信息配置文件 ...

  3. IO流(5)判断功能

    判断功能: * public boolean isDirectory():判断是否是目录 * public boolean isFile():判断是否是文件 * public boolean exis ...

  4. PAT 1101 Quick Sort[一般上]

    1101 Quick Sort(25 分) There is a classical process named partition in the famous quick sort algorith ...

  5. PAT 1042 Shuffling Machine[难]

    1042 Shuffling Machine (20)(20 分) Shuffling is a procedure used to randomize a deck of playing cards ...

  6. [LeetCode] 182. Duplicate Emails_Easy tag: SQL

    Write a SQL query to find all duplicate emails in a table named Person. +----+---------+ | Id | Emai ...

  7. Pycharm上python3运行unittest无法生成测试报告

    原文地址https://www.cnblogs.com/yoyoketang/p/7523409.html 前言 经常有人在群里反馈,明明代码一样的啊,为什么别人的能出报告,我的出不了报告:为什么别人 ...

  8. PIMPL(一)

    1 参考 <effective C++> 条款31:将文件间的编译关系降至最低 PIMPL Idiom: http://c2.com/cgi/wiki?PimplIdiom 2 什么是PI ...

  9. Unirest-拼装http请求发送rest接口

    public static Integer getInfo(String name) { HttpResponse<Integer> httpResponse = null; try { ...

  10. VS2010/MFC编程入门之三十六(工具栏:工具栏资源及CToolBar类)

    上一节中鸡啄米讲了菜单及CMenu类的使用,这一节讲与菜单有密切联系的工具栏. 工具栏简介 工具栏一般位于主框架窗口的上部,菜单栏的下方,由一些带图片的按钮组成.当用户用鼠标单击工具栏上某个按钮时,程 ...