• hdu 5724 Chess 博弈


    题目链接

    一个n行20列的棋盘。 每一行有若干个棋子。 两人轮流操作, 每人每次可以将一个棋子向右移动一个位置, 如果它右边有一个棋子, 就跳过这个棋子, 如果有若干个棋子, 就将这若干个都跳过。 但是棋子不能移出边界。

    如果没有办法移动了, 就算输。 问你先走的能否赢。

    只有20列, 所以预处理出所有状态的sg值。 然后直接异或就好了。

    然后sg[(1<<20)-1] = 0, 这是必输态, 其他的都可以dfs出来, 具体看代码。

    #include <bits/stdc++.h>
    
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<11
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, n, a) for(int i = a; i<n; i++)
    #define fi first
    #define se second
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 1e9+7;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    int sg[1<<22];
    int mex(int x)
    {
        if(~sg[x])
            return x;
        bool vis[20];
        memset(vis, false, sizeof(vis));
        for(int i = 0; i < 20; i++) {
            if(((1<<i)&x)==0 && ((1<<(i+1))&x)) {
                int j;
                for(j = i + 2; j < 20; j++) {
                    if(!(1<<j&x))
                        break;
                }
                for(int k = i+1; k <= j; k++) {
                    int sta = x^(1<<i)^(1<<k);
                    if(sta>=(1<<20))
                        break;
                    mex(sta);
                    vis[sg[sta]] = 1;
                }
            }
        }
        for(int i = 0; i < 20; i++)
            if(!vis[i])
                return sg[x] = i;
    }
    void init()
    {
        mem1(sg);
        sg[(1<<20)-1] = 0;
        for(int i = 0; i < (1<<20); i++) {
            if(sg[i] == -1) {
                mex(i);
            }
        }
    }
    int main()
    {
        init();
        int t, n, m, x;
        cin>>t;
        while(t--) {
            cin>>n;
            int ans = 0;
            for(int i = 0; i < n; i++) {
                scanf("%d", &m);
                int sta = 0;
                while(m--) {
                    scanf("%d", &x);
                    sta |= (1<<(20-x));
                }
                ans ^= sg[sta];
            }
            if(ans) {
                puts("YES");
            } else {
                puts("NO");
            }
        }
    }
  • 相关阅读:
    json&display
    postgresql AutoVacuum系统自动清理进程
    postgresql vacuum操作
    C++ 在.h文件中包含头文件和在.cpp文件中包含头文件有什么区别
    ResetEvent、CreateEvent、SetEvent
    《转载》C语言的移位操作符
    《转载》如何使用M6117D看门狗定时器复位系统
    《转载》 Bit,Byte,WORD,DWORD区别和联系
    $.messager.alert
    对一个或多个实体的验证失败
  • 原文地址:https://www.cnblogs.com/yohaha/p/5689958.html
Copyright © 2020-2023  润新知