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

HDU 5724 - Chess

时间:2016-07-25 00:04:36      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:

题意:
      一个n行20列的棋盘。 每一行有若干个棋子。
      两人轮流操作, 每人每次可以将一个棋子向右移动一个位置, 如果它右边有一个棋子, 就跳过这个棋子, 如果有若干个棋子, 就将这若干个都跳过。
      但是棋子不能移出边界。
      如果没有办法移动了, 就算输。 问你先走的能否赢。

分析:
      使用状压的SG.
      把每一列的答案异或起来.

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int SIZE = 1<<21;
 6 int SG[SIZE];
 7 int t, n, m;
 8 int GetSG(int x)
 9 {
10     if(SG[x] != -1) return SG[x];
11     int vis[50]={0},nxt=-1;
12     for(int i = 0; i < 20; i++)
13     {
14         if((x&(1 << i)) == 0) nxt=i;//离棋子最近的空格 
15         else if(nxt != -1) {
16             vis[GetSG(x ^ (1<<i) | (1<<nxt))] = 1;//该棋子走向空格
17         }
18     }
19     for(int i = 0; ; i++)
20     {
21         if(!vis[i]) return SG[x] = i;
22     }
23 }
24 void Init()
25 {
26     memset(SG,-1,sizeof(SG));
27     for(int i = 0; i <= 20; i++) SG[(1<<i) - 1] = 0;
28     for(int i = 1; i < (1<<20); i++) if(SG[i] == -1) GetSG(i);
29 }
30 int main()
31 {
32     Init();
33     scanf("%d",&t);
34     while(t--)
35     {
36         int ans = 0;
37         scanf("%d",&n);
38         while(n--)
39         {
40             scanf("%d",&m);
41             int x,p = 0;
42             while(m--)
43             {
44                 scanf("%d",&x);
45                 p |= 1 << (20 - x);//左右互换,走到20变为走到 1 
46             }
47             ans ^= SG[p];//所有答案异或 
48         }
49         if(ans) puts("YES");
50         else puts("NO");
51     }
52     return 0;
53 }

 

HDU 5724 - Chess

标签:

原文地址:http://www.cnblogs.com/nicetomeetu/p/5701888.html

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