zoukankan      html  css  js  c++  java
  • HDU 5724:Chess(博弈 + 状压)

    http://acm.hdu.edu.cn/showproblem.php?pid=5724

    Chess

    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(T100), indicates the number of test cases.

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

    Then n lines, the first integer of ith line is m(m20), indicates the number of chesses on the ith line of the chessboard. Then m integers pj(1pj20) 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列,每一行有m个棋子分别位于p,棋子只能往右走,如果有相邻的棋子,可以跳过这个棋子,当不能动的时候就输了,问先手能不能赢。

    思路:因为只有20列,可以状态压缩,打表枚举一行的所有状态,然后所有行状态的sg值异或起来就是答案。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define N 21
     6 
     7 int sg[1<<N];
     8 bool vis[21];
     9 
    10 int get_sg(int now)
    11 {
    12     memset(vis, 0, sizeof(vis));
    13     int i;
    14     //终止点为第20列,在这里的第20列为i = 0,因为i = 0的时候为必败点P
    15     //从第一列开始枚举,找到属于该状态的列,并且在该列下枚举,找到不属于该状态的列
    16     for(i = 20; i >= 0; i--) {
    17         if(now & (1 << i)) {
    18             int tmp = now;
    19             for(int j = i - 1; j >= 0; j--) {
    20                 if(!(now & (1 << j))) {
    21                     //这里异或的结果相当于第20-i列的棋子走到第20-j列的状态
    22                     tmp ^= ( (1 << i) ^ (1 << j) );
    23                     vis[sg[tmp]] = 1;
    24                     break;
    25                 }
    26             }
    27         }
    28     }
    29     for(i = 0; i <= 20; i++)
    30         if(!vis[i]) {
    31             sg[now] = i;
    32             break;
    33         }
    34 }
    35 
    36 int main()
    37 {
    38     sg[0] = 0;
    39     for(int i = 1; i <= (1 << 20); i++)
    40         get_sg(i);
    41     //打表枚举所有状态
    42     int t;
    43     scanf("%d", &t);
    44     while(t--) {
    45         int n, ans = 0, m, x, y;
    46         scanf("%d", &n);
    47         for(int i = 1; i <= n; i++) {
    48             scanf("%d", &m);
    49             x = 0;
    50             for(int j = 1; j <= m; j++) {
    51                 scanf("%d", &y);
    52                 x |= (1 << (20 - y));
    53                 //x = 所有有棋子的列加起来的状态
    54             }
    55             ans ^= sg[x];
    56             //最后的结果是所有行异或
    57 //            printf("ANS : %d
    ", ans);
    58         }
    59         if(ans == 0) puts("NO");
    60         else puts("YES");
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    H5调用相机和相册更换头像
    二分查找的递归解法以及希尔排序
    递归----经典问题:汉诺塔游戏
    递归----基础训练
    位运算-实现加减乘除
    位运算-出现k次与出现一次
    位运算-将整数的二进制进行奇偶位互换
    位运算-二进制中1的个数(三种解法)
    位运算-查找数组中唯一成对的数
    小小的总结一下2018年
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5757112.html
Copyright © 2011-2022 走看看