hdu-5724 Chess(组合游戏)

题目链接:

Chess

Time Limit: 2000/1000 MS (Java/Others)   

 Memory Limit: 65536/65536 K (Java/Others)

Problem Description

Alice and Bob are playing a special chess game on an n × 20 chessboard. There are several chesses on the chessboard. They can move one chess in one turn. If there are no other chesses on the right adjacent block of the moved chess, move the chess to its right adjacent block. Otherwise, skip over these chesses and move to the right adjacent block of them. Two chesses can’t be placed at one block and no chess can be placed out of the chessboard. When someone can’t move any chess during his/her turn, he/she will lose the game. Alice always take the first turn. Both Alice and Bob will play the game with the best strategy. Alice wants to know if she can win the game.

Input

Multiple test cases.

The first line contains an integer T(T≤100), indicates the number of test cases.

For each test case, the first line contains a single integer n(n≤1000), the number of lines of chessboard.

Then n lines, the first integer of ith line is m(m≤20), indicates the number of chesses on the ith line of the chessboard. Then m integers pj(1≤pj≤20)followed, the position of each chess.

Output

For each test case, output one line of “YES” if Alice can win the game, “NO” otherwise.

Sample Input

2

1

2 19 20

2

1 19

1 18

Sample Output

NO

YES

题意:

给一个n*20的棋盘,每行的一部分格子里面有棋子,现在每次可以选一个棋子把它挪到右边第一个空位上;现在问先手是否能必胜;

思路:

组合博弈的内容,先处理出所有状态的sg函数值,然后取异或值判断是否为零;

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
//#include <bits/stdc++.h>
#include <stack>

using namespace std;

#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));

typedef  long long LL;

template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<‘0‘||CH>‘9‘;F= CH==‘-‘,CH=getchar());
    for(num=0;CH>=‘0‘&&CH<=‘9‘;num=num*10+CH-‘0‘,CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
    if(!p) { puts("0"); return; }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + ‘0‘);
    putchar(‘\n‘);
}

const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=2e6+10;
const int maxn=500+10;
const double eps=1e-8;

int sg[N],vis[25];

inline int get_sg(int x)
{
    mst(vis,0);
    //cout<<x<<endl;
    for(int i=19;i>=0;i--)
    {
        if(x&(1<<i))
        {
            int temp=x;
            for(int j=i-1;j>=0;j--)
            {
                if(!(x&(1<<j)))
                {
                    temp^=(1<<i)^(1<<j);
                    //cout<<temp<<endl;
                    vis[sg[temp]]=1;
                    break;
                }
            }
        }
    }
    for(int i=0;i<=19;i++)if(!vis[i])return i;
    return 0;
}
inline void Init()
{
    For(i,0,(1<<20)-1)sg[i]=get_sg(i);
}
int main()
{
        Init();
        int t;
        read(t);
        while(t--)
        {
            int n,a,m,ans=0;
            read(n);
            while(n--)
            {
                int sum=0;
                read(m);
                For(i,1,m)
                {
                    read(a);
                    sum|=(1<<(20-a));
                }
                ans^=sg[sum];
            }
            if(ans)printf("YES\n");
            else printf("NO\n");
        }

        return 0;
}

  

时间: 2024-10-29 19:06:58

hdu-5724 Chess(组合游戏)的相关文章

HDU 5724 Chess(国际象棋)

HDU 5724 Chess(国际象棋) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 题目描述 Alice and Bob are playing a special chess game on an n × 20 chessboard. There are several chesses on the chessboard. They can mo

HDU 5724 Chess(博弈论)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5724 [题目大意] 给出一个n行,每行有20格的棋盘,棋盘上有一些棋子,每次操作可以选择其中一个棋子,将其移至最左端的空位,两个人轮流操作,无法操作者输,判断游戏胜负. [题解] 首先对于单行20格的游戏,这是一个NIM游戏,将20格的情况状态压缩,对于每种情况递归求其mex集合,计算其sg值,sg值为0的状态为必败态. 而对于可以拆分为多组NIM游戏的游戏,其sg值为拆分出的多组游戏的sg值的

HDU 5724 Chess(SG函数)

Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2605    Accepted Submission(s): 1092 Problem Description Alice and Bob are playing a special chess game on an n × 20 chessboard. There are s

HDU 5724 Chess

因为一行最多只有20个数,也就是说只有(1<<20)种状态,向右移动表示小的数推向了大的数.可以用SG函数预处理出所有情况.然后把每一行的SG函数值异或一下,非零则必胜,否则输. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #

hdu 5724 Chess 博弈

题目链接 一个n行20列的棋盘. 每一行有若干个棋子. 两人轮流操作, 每人每次可以将一个棋子向右移动一个位置, 如果它右边有一个棋子, 就跳过这个棋子, 如果有若干个棋子, 就将这若干个都跳过. 但是棋子不能移出边界. 如果没有办法移动了, 就算输. 问你先走的能否赢. 只有20列, 所以预处理出所有状态的sg值. 然后直接异或就好了. 然后sg[(1<<20)-1] = 0, 这是必输态, 其他的都可以dfs出来, 具体看代码. #include <bits/stdc++.h>

HDU 4832 Chess 排列组合 DP

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 351    Accepted Submission(s): 124 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘 上的走法遵循十字

组合游戏 - SG函数和SG定理

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质: 1.所有终结点是 必败点 P .(我们以此为基本前提进行推理,换句话说,我们以此为假设) 2.从任何必胜点N 操作,至少有一种方式可以进入必败点 P. 3.无论如何操作,必败点P 都只能进入 必胜点 N. 我们研究必胜点和必败点的目的时间为题进行简化,有助于

HDU 4832 Chess (DP)

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 24    Accepted Submission(s): 10 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字路线.

组合游戏(博弈)

昨天看大白书翻到了组合游戏这章,看着发觉原来是博弈论的内容,于是便看下去了.真是不看不知道,一看才知道自己的水平有多弱,不过好在还是集中精神地看了大部分.从Nim游戏(n堆石子,每人每次可以从任意一堆中取至少1个.至多整堆的石子,不能取者为输)开始讲起,引入必胜态.必败态的概念—— 1. 一个状态是必败状态当且仅当它的所有后继都是必胜状态. 2. 一个状态是必胜状态当且仅当它至少有一个后继是必败状态. 这是刘汝佳大神说的,说得通俗一点就是,必败态的所有后继都是必胜态,必胜态只需有一个后继是必败态