码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5724 Chess(博弈论)

时间:2016-11-16 14:43:43      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:ret   font   题解   ems   流操作   ons   int   else   博弈   

 

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

 

【题目大意】

    给出一个n行,每行有20格的棋盘,棋盘上有一些棋子,每次操作可以选择其中一个棋子,将其移至最左端的空位,两个人轮流操作,无法操作者输,判断游戏胜负。

 

【题解】

  首先对于单行20格的游戏,这是一个NIM游戏,将20格的情况状态压缩,对于每种情况递归求其mex集合,计算其sg值,sg值为0的状态为必败态。

  而对于可以拆分为多组NIM游戏的游戏,其sg值为拆分出的多组游戏的sg值的异或和。

  预处理所有状态的sg值,对于每种读入的棋盘情况,直接求出解即可。

 

【代码】

#include <cstdio>
#include <cstring>
using namespace std; 
const int N=1<<20;
int sg[N],T,n,m,x;
int dfs(int x){
    if(sg[x]!=-1)return sg[x];
    int mex[50]={0},pos=-1;
    for(int i=0;i<20;i++){
        if((x&(1<<i))==0)pos=i;
        else if(pos!=-1)mex[dfs(x^(1<<i)|(1<<pos))]=1;
    }for(int i=0;i<N;i++)if(!mex[i])return sg[x]=i;
}
void init(){
    memset(sg,-1,sizeof(sg));
    for(int i=0;i<=20;i++)sg[(1<<i)-1]=0;
    for(int i=1;i<N;i++)dfs(i);
}
int main(){
    init();
    scanf("%d",&T);
    while(T--){
        int SG=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&m);
            int tmp=0;
            for(int j=1;j<=m;j++)scanf("%d",&x),tmp|=(1<<(20-x));
            SG^=sg[tmp];
        }if(SG)puts("YES");
        else puts("NO");
    }return 0;
}

  

HDU 5724 Chess(博弈论)

标签:ret   font   题解   ems   流操作   ons   int   else   博弈   

原文地址:http://www.cnblogs.com/forever97/p/hdu5724.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!