HDU5724 Chess 阶梯博弈变形 2016 Multi-University Training Contest 1




题意:给定一个n行20列的棋盘,并给定棋子(多个)的初始位置,两个人轮流移动棋子,最后不能移动棋子者输    移动规则:一次只能移动一个棋子,如果该棋子右边无棋子,则可以向右移动一格,如果该棋子右边有棋子(一个或多个连续),则该棋子可以跳过右边这些的棋子,向右移动到最靠近该棋子的空格。

思路:阶梯博弈变形:

 

阶梯博弈(Staircase Nim):

博弈在一列阶梯上进行,每个阶梯上没有石子或放着若干个石子。两个人进行阶梯博弈,每一步则是将阶梯(不是第一层的阶梯)上的若干个石子移到(某些指定的)低阶的阶梯去,最后没有石子可以移动的人输。


阶梯博弈可以利用游戏的限制转化成Nim解决:由于某个阶梯上的石子移动到不能移动时所需的步数要么是奇数,要么是偶数。对于偶数步,对方用哪些石子走一步你也用哪些石子走一步,从而不影响游戏结果。所以只对奇数阶的石子求Nim就行。

该题博弈在一个N个格子的方块上进行,每个方块上至多有一个石子,每次可以选择一个石子向右移动到最近的空位,不能移动石子的人输,如下图所示:


设函数F[i]表示第i个石子移动到不能移动所需要的步数。
然后我们来观察某一次移动,假设图中的2跳到了4的后面,我们可以来观察一下所有石子的F函数有什么变化:


首先对于1及其之前的石子,它们的F函数显然不变。
同样,对于移动后的2之后的石子,它们的F函数也不变。

那么变化的就是2,3,4这三个石子的F值,变化了多少?每一个减少了1
那么,如果我们把这个函数F[]看做台阶的阶数的话,乃是不是觉得有一点熟悉的感觉了~
没错!就是阶梯博弈

这里看似只能移动一个棋子,但是实际上导致了多个棋子的F值减少一,即相当于将某台阶上任意个棋子移动到下一台阶,所以此题只需将F值为奇数的棋子进行统计,然后对F值相同的棋子的数目取Nim即可

 



#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        int x=0;//注意该类题异或时初始值应该为0
         for(int i=0;i<n;i++){
            int qipan[21];
            int f[21];
            int shizishu[21];
            int shizishu_cnt=0;
            memset(shizishu,0,sizeof(shizishu));
            memset(qipan,0,sizeof(qipan));
            memset(f,0,sizeof(f));
            int m;
            scanf("%d",&m);
            for(int j=0;j<m;j++){
                int p;
                scanf("%d",&p);
                qipan[p]=1;
            }
            for(int k=1;k<=20;k++){
                if(qipan[k]==1){
                    for(int l=k+1;l<=20;l++)
                        if(qipan[l]==0) f[k]+=1;
                }
                if(f[k]%2==1) shizishu[f[k]]++;
            }
            for(int y=1;y<=20;y++)
                if(shizishu[y]!=0) x^=shizishu[y];
        }
        if(x!=0) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

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(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
 
http://acm.hdu.edu.cn/showproblem.php?pid=5724
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值