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 getG(int num) {
    int vis[210];
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= num; i++) {
        int t = 0;
        if(num - i - 2 >= 0)
            t ^= g[num-i-2];
        if(i - 3 >= 0)
            t ^= g[i-3];
        vis[t] = 1;
    }
    for(int i = 0; ; i++)
        if(!vis[i])
            return i;
}
void init() {
    memset(g, 0, sizeof(g));
    g[1] = g[2] = g[3] = 1;
    for(int i = 4; i <= 200; i++) {
        g[i] = getG(i);
    }
}
bool check(int flag) {
    int ret = 0;
    int vis[210]; memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= len; i++) {
        if(s[i] == ‘X‘) {
            if(i - 2 >= 1) {
                vis[i-2] = 1;
            }
            if(i - 1 >= 1) {
                vis[i-1] = 1;
            }
            if(i + 1 <= len) {
                vis[i+1] = 1;
            }
            if(i + 2 <= len) {
                vis[i+2] = 1;
            }
            vis[i] = 1;
        }
    }
    int cnt = 0;
    /*if(flag == 21)
        for(int i = 1; i <= len; i++)
            printf("%d ", vis[i]);
    puts("");*/
    for(int i = 1; i <= len; i++) {
        if(!vis[i]) cnt++;
        else {
            ret ^= g[cnt];
            cnt = 0;
        }
    }
    ret ^= g[cnt];
    /*if(flag == 1)
        printf("%d\n", ret);*/
    return ret == 0;
}

bool solve() {
    len = strlen(s + 1);

    int vis[210]; memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= len; i++) {
        if(s[i] == ‘X‘) {
            if(i - 2 >= 1) {
                vis[i-2] = 1;
            }
            if(i - 1 >= 1) {
                vis[i-1] = 1;
            }
            if(i + 1 <= len) {
                vis[i+1] = 1;
            }
            if(i + 2 <= len) {
                vis[i+2] = 1;
            }
            vis[i] = 1;
        }
    }
    for(int i = 1; i <= len; i++) {
        if(i - 1 >= 1 && i + 1 <= len && s[i-1] == ‘X‘ && s[i+1] == ‘X‘)
            ans.push_back(i);
        if(i - 2 >= 1 && s[i-2] == ‘X‘ && s[i-1] == ‘X‘)
            ans.push_back(i);
        if(i + 2 <= len && s[i+1] == ‘X‘ && s[i+2] == ‘X‘)
            ans.push_back(i);
    }
    if(ans.size() != 0) return 1;
    for(int i = 1; i <= len; i++) {
        if(s[i] == ‘.‘ && !vis[i]) {
            //printf("check %d\n", i);
            s[i] = ‘X‘;
            if(check(i))
                ans.push_back(i);
            s[i] = ‘.‘;
        }
    }
    return ans.size() != 0;
}

int main() {
    /*freopen("in.txt", "r", stdin);
    freopen("out1.txt", "w", stdout);*/
    init();
    int t;
    //for(int i = 0; i <= 200; i++) printf("%d ", g[i]);
    scanf("%d", &t);
    while(t--) {
        ans.clear();
        scanf("%s", s + 1);
        bool flag = solve();
        if(flag) {
            puts("WINNING");
            for(int i = 0; i < ans.size(); i++){
                if(i == 0) printf("%d", ans[i]);
                else printf(" %d", ans[i]);
            }puts("");
        }
        else puts("LOSING\n");
    }
}
时间: 2024-08-02 09:00:25

UVA 10561 Treblecross的相关文章

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

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

Treblecross(uva 10561)

题意:一个 1 × n 的棋盘,有 X 和 :,当棋盘上出现三个连续的X 时游戏结束,两人轮流操作,每次能把一个 : 变成 X,问先手必胜方案数以及先手可以放的位置. /* 对于先手,当有一个'X'时,它周围的两个格子就都不能放'X'了,所以这样游戏就被分成了几个部分,据此设定SG函数. */ #include<iostream> #include<cstdio> #include<cstring> #define N 210 using namespace std;

UVa 10561 (SG函数 递推) Treblecross

如果已经有三个相邻的X,则先手已经输了. 如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜. 除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,队手下一轮再放一个就输了. 最后当“禁区”布满整行,不能再放X了,那个人就输了. 每放一个X,禁区会把它所在的线段“分割”开来,这若干个片段就可以看做若干个游戏的和. 设g(x)表示x个连续格子对应的SG函数值,递推来求g(x): g(x) = mex{ g(x-3), g(x-4), g(x-5), g(x-6) xor g(1),

UVa10561

10561 TreblecrossTreblecross 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 emptycell, and if that results i

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te