UVA - 10561 Treblecross (博弈数学&SG函数)

来源:互联网 发布:华为网络在线客服 编辑:程序博客网 时间:2024/05/14 10:15
Treblecross
Time Limit: 3000MS  64bit IO Format: %lld & %llu

Submit Status uDebug

Description

Download as PDF

借鉴自:http://blog.csdn.net/yeyeyeguoguo/article/details/47068427


题意:

n个格子排成一行,其中一些格子有字符X。两个游戏中轮流操作,每次可以将一个X放在空格上。若出现连续3个X,则该游戏中胜。给你一串字符问你先手必胜还是必败,必胜的话输出所有必胜策略(就是当前局势下你走哪一步可以确认为必胜,所有种类都要输出,理解了半天)

分析:

一行格子可被X分为两部分,一部分为X及其禁区(左右半径两格内),另一部分为安全区域可进行子游戏,根据SG定理,可通过计算若干个游戏的和来得到最终结果。

SG函数可通过SG定理得到,借鉴的大神代码,思路清晰,比白书好懂多了。。

#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;#define INF 0x3f3f3f3fconst long long N=205;const long long mod=1e9;const double PI=acos(-1.0);typedef long long ll;int t,res[N],way,len,sg[N];char str[N];int judge() {    for (int i = 0; i < len - 2; i++) {        if (str[i] == 'X' && str[i + 1] == 'X' && str[i + 2] == 'X')            return true;    }    return false;}int SG(int x) {    int vis[N];    if (sg[x] != -1) return sg[x];    if (x == 0) return sg[x] = 0;    memset(vis, false, sizeof(vis));    for (int i = 1; i <= x; i++) {        int t = SG(max(0, i - 3))^SG(max(0, x - i - 2));        vis[t] = true;    }    for (int i = 0; i < N; i++) {        if (vis[i]) continue;        return sg[x] = i;    }    return 0;}int GetRes() {    for (int i=0; i<len; i++) {        if (str[i]=='.') {            str[i]='X';            if (judge()) {                str[i]='.';                return false;            }            str[i]='.';        }    }    int ans=0,num=0;    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')) {            ans ^= SG(num);            num = 0;        }        else num++;    }    ans^=SG(num);    return ans==0;}void solve() {    way=0;    len=strlen(str);    for (int i=0; i<len; i++) {        if (str[i]!='.') continue;        str[i]='X';        if (judge()||GetRes()) {            res[way++]=i+1;        }        str[i]='.';    }}int main() {    memset(sg, -1, sizeof(sg));    cin>>t;    while (t--) {        scanf("%s",str);        solve();        if (way==0) cout<<"LOSING\n\n";        else {            cout<<"WINNING\n"<<res[0];            for (int i=1; i<way; i++) {                cout<<" "<<res[i];            }            cout<<endl;        }    }    return 0;}


0 0
原创粉丝点击