HDU5724 Chess

来源:互联网 发布:中国9月经济数据 编辑:程序博客网 时间:2024/06/06 00:01

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5724


【题意】Alice 和 Bob 在一个n*20的棋盘上下棋,每行有m个棋子(m<=20)。两人轮流移动棋子,每次只能且必须移动一个棋子,棋子只能移动到该棋子右边最近的一个不超过棋盘边界的空位。当没有棋子可以移动的时候判输。


【分析】简单的博弈题。因为每行位子的数目是固定的,可以用二进制数表示一行所有可能的状态,求出所有状态的SG值,最后每行异或一下得到答案。


【代码】

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;#define MAXN 100100    int sg[1<<20];vector<int> v;bool cpr(int x,int y){    return x<y;}int main(){    int T,n,m,p;    cin>>T;    int len=1<<20;     for(int i=1;i<len;++i){        int fla=0;        for(int j=1;(1<<j)<=i;++j)            if(i==(1<<j)-1){                fla=1;                break;            }        if(fla){            sg[i]=0;            continue;        }        v.clear();        for(int j=1;(1<<j)<=i;++j)            if((i&(1<<j))!=0){                for(int k=j-1;k>=0;k--){                    if((i&(1<<k))==0){                        v.push_back(sg[i^(1<<j)^(1<<k)]);                        break;                    }                }            }        int x=0;        sort(v.begin(),v.end(),cpr);        for(int j=0;j<v.size();++j){            if(v[j]>x)                break;            if(v[j]==x)                x++;        }        sg[i]=x;    }    while(T--){        int ans=0;        scanf("%d",&n);        for(int i=0;i<n;++i){            scanf("%d",&m);            int a,tmp=0;            for(int j=0;j<m;++j){                scanf(" %d",&a);                tmp^=(1<<(20-a));            }            ans^=sg[tmp];        }        if(ans)            cout<<"YES\n";        else            cout<<"NO\n";     }}





0 0