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

poj2975 Nim 博弈

时间:2015-05-26 09:17:21      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:acm   博弈   

      自从省赛结束了,好久都做过博弈题了,感觉都快忘了。今天找了几题练练手,在做过程中,感觉这道题挺有意思的。题目的意思是说,在Nim游戏中,先手有几种方式让 Nim 和变为0。(不知道Nim游戏的,请参考:这里
       其实我觉得这道题就是披着博弈的外衣,然后来考查你异或运算符(^)的使用的。在做题之前,我们想要了解异或运算符(^)的一个重要的性质:
       现在我们有三个整数a, b, c: 
       我们假设c = a ^ b, 那么我们可以得到 b = c ^ a, a = b ^ c(交换律对异或运算符是成立的)。
       现在我们在来分析一下这道问题,假设sum 为 Nim和,a为某一堆的个数,b为其余堆的Nim和。那么我们就可以得到 sum = a ^ b。我们的任务是让sum变为零,所以我们只要让 a 等于 b,就可以达到我们的目的了。有上述的性质,我们可以将式子边形为b = sum^a。
因为b我们不好改变,所以我们只能从a下手。换而言之,我们只需让a变为b就可以达到目的。所以题目就变成了,存在多少个能够变为b的a。也就是说,有多少个a大于b(因为题目说石子只能减少)。
      现在问题就变得十分容易了,从这一题我们可以得到一个结论。简化问题的能力是至关重要的,在解题过程中重点就是要培养这种能力。
【代码如下】
#include <stdio.h>
#define MAXN 1000 + 10
int main(){
    int n, Nim[MAXN], ans, cnt, i;
    while(scanf("%d",&n),n){
        for(i = ans = 0; i < n; i++){
            scanf("%d", &Nim[i]);
            ans ^= Nim[i];
        }
        for(i = cnt = 0; i < n; i++){
            if((ans^Nim[i]) < Nim[i]) cnt++;
        }
        printf("%d\n", cnt);
    }
    return 0;
}


poj2975 Nim 博弈

标签:acm   博弈   

原文地址:http://blog.csdn.net/luomingjun12315/article/details/46003143

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