zoukankan      html  css  js  c++  java
  • LightOJ 1229 Treblecross(SG函数打表 + 遍历)题解

    题意:给你一串含“.”和“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 = 200 + 10;
    const int seed = 131;
    const ll MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    int sg[maxn], s[maxn], ans[maxn], pos;
    char str[maxn];
    void getSG(){
        sg[0] = 0;
        for(int i = 1; i < maxn; i++){
            memset(s, 0, sizeof(s));
            for(int j = 1; j <= i; j++){
                int t = 0;
                if(i - j - 2 >= 0) t ^= sg[i - j - 2];
                if(j - 3 >= 0) t ^= sg[j - 3];
                s[t] = 1;
            }
            for(int j = 0; j < maxn; j++){
                if(!s[j]){
                    sg[i] = j;
                    break;
                }
            }
        }
    }
    bool check(){
        ll ret = 0;
        int num = 0, len = strlen(str);
        for(int i = 0; i < len; i++){
            if(str[i] == 'X'){
                if((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')){
                    return false;
                }
                if(str[i - num - 1] == 'X' && i - num - 1 >= 0)
                    num -= 2;
                num -= 2;
                if(num >= 0) ret ^= sg[num];
                num = 0;
            }
            else{
                num++;
            }
        }
        if(str[len - 1 - num] == 'X' && len - 1 - num >= 0)
                num -= 2;
        if(num >= 0) ret ^= sg[num];
        return ret == 0;
    }
    void solve(){
        pos = 0;
        int len = strlen(str);
        for(int i = 0; i < len; i++){
            if(str[i] == '.'){
                str[i] = 'X';
                if(i + 1 < len && i - 1 >= 0 && str[i + 1] == 'X' && str[i - 1] == 'X'){
                    ans[pos++] = i + 1;
                }
                else if(i + 1 < len && i + 2 < len && str[i + 1] == 'X' && str[i + 2] == 'X'){
                    ans[pos++] = i + 1;
                }
                else if(i - 2 >= 0 && i - 1 >= 0 && str[i - 2] == 'X' && str[i - 1] == 'X'){
                    ans[pos++] = i + 1;
                }
                else if(check()){
                    ans[pos++] = i + 1;
                }
                str[i] = '.';
            }
        }
    }
    int main(){
        int T, Case = 1;
        getSG();
        scanf("%d", &T);
        while(T--){
            scanf("%s", str);
            solve();
            printf("Case %d:", Case++);
            if(pos == 0) printf(" 0
    ");
            else{
                for(int i = 0; i < pos; i++){
                    printf(" %d", ans[i]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    mongodb
    python中读取文件的read、readline、readlines方法区别
    uva 129 Krypton Factor
    hdu 4734
    hdu 5182 PM2.5
    hdu 5179 beautiful number
    hdu 5178 pairs
    hdu 5176 The Experience of Love
    hdu 5175 Misaki's Kiss again
    hdu 5174 Ferries Wheel
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9716122.html
Copyright © 2011-2022 走看看