zoukankan      html  css  js  c++  java
  • 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");
            }
        }
    }
  • 相关阅读:
    Pascal's Triangle II
    Pascal's Triangle
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock
    Populating Next Right Pointers in Each Node
    path sum II
    Path Sum
    [转载]小波时频图
    [转载]小波时频图
    [转载]Hilbert变换及谱分析
  • 原文地址:https://www.cnblogs.com/yohaha/p/5689958.html
Copyright © 2011-2022 走看看