HDU 5724 Chess (状压+sg)

来源:互联网 发布:python 黑帽子 笔记 编辑:程序博客网 时间:2024/06/05 03:01

题意:

给出n行,每行20列,放上若干个棋子,每个棋子只能移动到其右侧第一个空位,不能移动的lost

思路:

对于每行,有2^20种状态,虽然不多,但是存不下,因此要用位来压,1<<i表示了第20-i位数字是0 还是1,即棋子还是空。

对于每行来说,因为行是一个子问题,无法再次拆解,因此直接对于行来打sg函数的表。记录每个子问题的答案,异或便是最终答案

#include<cstdio>#include<cstring>using namespace std;const int maxn=1<<20;int SG[maxn],f[maxn],vis[20];void getSG(){    memset(SG,0,sizeof(SG));    for(int s=0;s<(1<<20);++s)    {        memset(vis,0,sizeof(vis));        for(int i=19;i>=0;i--)        {            if(!(s>>i&1))                continue;            for(int j=i-1;j>=0;j--)            {                if(!(s>>j&1))                {                    vis[SG[s^(1<<j)^(1<<i)]]=1;                    break;                }            }        }        for(int i=0;i<=20;i++)        {                if(!vis[i])                {                    SG[s]=i;                    break;                }        }    }}int main(){    getSG();    int t;    scanf("%d",&t);    while(t--)    {        int n,m,k;        scanf("%d",&n);        int res=0;        for(int i=0;i<n;i++)        {            scanf("%d",&m);            int s=0;            while(m--)            {                scanf("%d",&k);                s+=1<<20-k;            }            res^=SG[s];        }        if(res) puts("YES");        else puts("NO");    }    return 0;}


原创粉丝点击