Chess HDU

来源:互联网 发布:2016年淘宝大数据分析 编辑:程序博客网 时间:2024/05/24 05:10

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值,然后将所有的行的sg值异或起来就可以了。对于每一行,我们如果将放置棋子的位置标记为1,空位标记为0,那么就可以将每一行棋子放置的状态转成二进制进行压缩,因为一行最多20列,所以总共1<<20-1 种状态。然后预先用sg函数求出每种状态的sg值保存即可。

代码如下

#include <iostream> #include <cmath>#include <algorithm>#include <cstring>#include <queue>#include <cstdio>#include <map>using namespace std; #define ll long long int const int maxn=(1<<20);int sg[maxn];//sg[n] n表示状态bool vis[50];void get_sg(int x){    int bit[25];    int tol=0;    int xx=x;    while(xx)//转化成二进制    {        bit[tol++]=(xx%2);        xx/=2;    }    memset(vis,0,sizeof(vis));    int pos=-1;    for(int i=0;i<tol;i++)    {        if(bit[i]==1&&pos==-1)//如果当前位置是棋子,但是在它右边都没空位则无法跳         continue;        else if(bit[i]==1)//如果当前是棋子        vis[sg[x-(1<<i)+(1<<pos)]]=1;//它所能达到的状态        else         pos=i;//记录最近的空位置     }    for(int i=0;i<50;i++)    if(!vis[i])    {        sg[x]=i;        break;     } }void init(){    sg[0]=0;    sg[1]=0;    for(int i=2;i<=(1<<20);i++)    get_sg(i);}int main(){    init();    int T;    scanf("%d",&T);    while(T--)    {        int k;        scanf("%d",&k);        int ans=0;        while(k--)        {            int m;            scanf("%d",&m);            int sum=0;            while(m--)            {                int x;                scanf("%d",&x);                sum+=(1<<(20-x));            }            ans^=sg[sum];        }        if(ans) printf("YES\n");        else printf("NO\n");    }}
原创粉丝点击