ACM-博弈之Nim和

在这篇和下一篇文章中,我们将进击博弈论中稍微高级一些的内容。总的来说,这些算法的证明比较麻烦,但是如果我们避开理论,用它们来解决问题的话,大家会发现出奇的简单。至于需不需要深究这些算法的内在原理,就要看大家自身的需求了。好了,进入正题吧,下面我们将先讨论Nim和:

总的来说,Nim和其实就是一个结论,什么结论呢?就是L.Bouton这个人,在1902年的时候得出的一个定理。其内容就是:状态(x1,x2,x3......),为必败状态当且仅当x1 xor x2 xor x3 xor......=0,其中的xor是异或的意思。这个就是Nim和了,还是比较简单的。

如果要想证明这个结论,可以参考刘汝佳训练指南第135页。其次,既然定理都叫nim了,那当然它是用来解决nim的,那什么又是nim呢?其实它是个游戏,叫nim游戏,之前我们接触的双人轮流操作游戏都有点nim的感觉,但是nim游戏是有定义,或者说是条件的,即:

(1)两个参与游戏的人轮流任选一个集合操作,这个操作不能有特殊条件限制(这个需要分析对游戏有没有影响)

(2)有限的状态集,即游戏总能在状态不重复的条件下结束

(3)没有平局,谁不能操作谁输,另一方获胜

其实真正的nim游戏是在3个集合上的操作,但是Nim和适合多个操作集合的nim游戏,但是如果一个游戏不是nim,然后用Nim和去解得话,很有可能得出错误的答案。话不多说,就先上一道题来试一下水,看看Nim和的威力,HDOJ:5011,传送门(点击打开链接),题目如下:

Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 437    Accepted Submission(s): 340


Problem Description
Here is a game for two players. The rule of the game is described below: 

● In the beginning of the game, there are a lot of piles of beads.

● Players take turns to play. Each turn, player choose a pile i and remove some (at least one) beads from it. Then he could do nothing or split pile i into two piles with a beads and b beads.(a,b > 0 and a + b equals to the number of beads of pile i after removing) 

● If after a player's turn, there is no beads left, the player is the winner.

Suppose that the two players are all very clever and they will use optimal game strategies. Your job is to tell whether the player who plays first can win the game.
 

Input
There are multiple test cases. Please process till EOF.

For each test case, the first line contains a postive integer n(n < 10 5) means there are n piles of beads. The next line contains n postive integer, the i-th postive integer a i(a i < 2 31) means there are a i beads in the i-th pile.
 

Output
For each test case, if the first player can win the game, ouput "Win" and if he can't, ouput "Lose"
 

Sample Input
  
  
1 1 2 1 1 3 1 2 3
 

Sample Output
  
  
Win Lose Lose
 


题意:

大家熟知的题意。有许多堆珠子,然后告诉你每堆珠子的数量,接下来就是两个人轮流操作了,每人每轮从任意一堆中拿走至少1个珠子,然后这个人可以对这堆珠子采取两种做法,1、什么事也不做(值当没说),2、将这堆珠子,分成另外两堆不为零的珠子。最后,没有珠子拿的人输,问第一个拿的人是赢了还是输了。

分析:

首先分析,会不会存在固定的规律?显然,题意中说可以自由操作堆得数量,状态可以改变,规律也就很难找了,当然递推也不太适合,因为太多不确定了。那要不试试Nim和?马上再读一遍题,唯一需要确定的是那个将堆一分为二的操作,分析了一下,其实它对游戏的本质是没有影响的,游戏最终还是在有限的状态集中进行,于是 发现这个游戏满足nim游戏的规则,那么决定就用Nim和了,不就是判断一下初始状态是必胜还是必败嘛。然后,,,,过了,,,,,,。代码如下

#include <cstdio>

int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        int sum = 0;                  // Nim和初始为0
        for(int i=0; i<n; ++i)
        {
            __int64 tmp;
            scanf("%I64d", &tmp);
            sum ^= tmp;               // 求出Nim和,值为0则初始状态必败,否则必胜
        }
        printf("%s\n", sum ? "Win" : "Lose");
    }
    return 0;
}

看来Nim和还是比较好用的,其它类似的题目还有,ZOJ:3067,大家可以拿来练习。接下来,我们讨论一下博弈论中的另一个经典:SG函数,传送门(点击打开链接)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值