Nim游戏是组合游戏(Combinatorial Games)的一种,属于“Impartial Combinatorial Games”(以下简称ICG)。

通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。

        我们都知道,对于N堆石子,判断第一个人是否赢是将每个石子进行异或运算,如果结果为0则第一个人取得必输,否则必赢。

        但主要是为什么用异或?为什么等于零则是先者必输?

        首先先说一下大家都知道的定义吧:P-position和N-position。

        P-position:P即Previous,该局面为P-position,则代表着这个局面先行者必输,后行者必赢。

        N-position:N即Next,该局面为N-position,则代表着这个局面的后行者必输,先行者必赢。

很显然,对于无法移动的局面(Terminal position)为P-position;可以移动到P-position局面的必为N-position局面(就是这个局面是先行者必输的话,它的上一个局面一定是后行者必输);所有移动都导致N-position局面的是P-position。

        也就是说,对于一个局面A是 P-position还是N-position,如果它的子局面(所谓子局面就是这个局面的能够发展成的后续局面,比如两个石子堆个数为(3,3),那么它的子局面为(0,3)(1,3)(2,3))存在先者必输P-position的局面,那么局面A就是后者必输N-position的局面,如果它的子局面全部是后者必输N-position的局面,那么局面A就是先者必输P-position的局面(子局面的后者就是局面A的操作者)。

为此我们要判断的就是一开始是属于什么局面,根据上述定义可知这个局面的判定取决于它的子局面,而它的子局面又取决于它的子子局面……直到这个局面能够独立判断是P-position还是N-position,然后再回溯判断,对于这个递归的算法你可能已经敏锐地看到有大量重复的子问题了,需要记忆化搜索或DP,这实际上也就是博弈论的本质而已,只是我们存在一种比搜索更优的方法——异或。

为什么用异或呢?因为异或有一种我们需要的神奇的性质——消去律。

1.对于Terminal position只有一个,也就是全为0,结果也为0,故先行者必输。

2.某个局面(a1,a2,...,an),若a1^a2^......^an=k(k不等于0),则必有一种局面ai能够通过合法的步骤转换为ai',使结果变为0(k二进制中的某一位中的1必定是某个ai贡献过来的),其中ai^k=ai'<ai(ai在k的二进制下最高位是1),所以是后行者必输。

3.某个局面(a1,a2,...,an),若a1^a2^......^an=0,若ai能够通过合法的步骤转换成另一个局面ai'使结果也为0,那么a1^a2^..^ai^...^an=a1^a2^..^ai'^...^an,根据消去律,得到ai=ai',这是不合法的移动(因为还是它本身),所以是先行者必输。

而这样,我们就可以在O(n)内知道应该是先行还是后行了。

关于SG函数,我们先定义一种作用在集合的运算mex,定义结果为该集合中未出现的最小非负整数,如mex{0,1,2,4}=3、 mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:g(x)=mex{ g(y) | y是x的后继(就是子局面) }。

实际上,所以Nim游戏都可以抽象成一个模型:一个有向图中,一个棋子代表着当前局面,每个顶点代表着每个局面,而每位选手则负责移动棋子,直到某个选手无法移动棋子则为负。

所以对于SG函数的性质,跟上面所讲的1,2,3是一样的:

1.对于Terminal position对应的顶点,就是没有出边,其g(x)=0;

2.若该点ai的g(ai)不为0,则它的后继里存在一个顶点ai'它的g(ai')=0;

3.若该点ai的g(ai)=0;则它的后继里没有一个顶点ai'它的g(ai')=0。

事实上,如果有多堆石子,我们可以把每堆石子都抽象成一个棋子在图中移动,那么我们所要做的就是讲每个棋子所在顶点的SG值算出来,异或一下即可。

稍微变一下,有n堆石子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗, 我们可以把它看作3个子游戏,第1个子游戏只有一堆x颗石子,每次可以取1、2、3颗,很容易看出x颗石子的局面的SG值是x%4(数学归纳法可以证明)。第2个子游戏也是只有一堆 石子,每次可以取奇数颗,经过简单的画图可以知道这个游戏有x颗石子时的SG值是x%2。第3个游戏有n-2堆石子,就是一个Nim游戏。对于原游戏的每 个局面,把三个子游戏的SG值异或一下就得到了整个游戏的SG值,然后就可以根据这个SG值判断是否有必胜策略以及做出决策了。

g(x)=b,说明当前局面可以移动到g(a)=b-1,b-2,b-3.......1,0上。

所以,对于我们来说,我们是将一个复杂的游戏分成许许多多若干个简单的小游戏,再分别求出SG值,再全部异或起来就是原游戏的SG值了。

博弈论之Nim游戏的更多相关文章

  1. 博弈论入门——Nim游戏引入

    说实话,我真的对这个游戏看得是一脸懵逼,因为(我太弱了)我没有明白一些变量的意思,所以一直很懵,现在才明白,这让我明白博弈论(还可以骗钱)博大精深; 以下是我自己思考的过程,也许不严谨,但是最终明白了 ...

  2. 博弈论(nim游戏,SG函数)

    说到自己,就是个笑话.思考问题从不清晰,sg函数的问题证明方法就在眼前可却要弃掉.不过自己理解的也并不透彻,做题也不太行.耳边时不时会想起alf的:"行不行!" 基本的小概念 这里 ...

  3. 【博弈论】Nim游戏

    百度百科 Definition 这样的游戏被称为Nim游戏: 1.有两个玩家,轮流进行操作 2.是公平游戏.即面对同一局面两个玩家所能进行的操作是相同的.例如中国象棋不是公平游戏.因为面对同一个局面, ...

  4. 博弈论入门之nim游戏

    更好的阅读体验点这里 nim游戏 nim游戏 有两个顶尖聪明的人在玩游戏,游戏规则是这样的: 有\(n\)堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿),没法拿的人失败.问谁会胜利 ni ...

  5. 【博弈论】浅谈泛Nim游戏

    Nim游戏在ACM中碰到了,就拎出来写写. 一般Nim游戏:有n堆石子,每堆石子有$a_i$个,每次可以取每堆石子中$[0,a_i-1]$,问先手是否有必胜策略. 泛Nim游戏:每堆石子有$a_i$个 ...

  6. [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)

    今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...

  7. Nim游戏与SG函数 ——博弈论小结

    写这篇博客之前,花了许久时间来搞这个SG函数,倒是各路大神的论文看的多,却到底没几个看懂的.还好网上一些大牛博客还是性价比相当高的,多少理解了些,也自己通过做一些题加深了下了解. 既然是博弈,经典的N ...

  8. BZOJ_3105_[cqoi2013]新Nim游戏_线性基+博弈论

    BZOJ_3105_[cqoi2013]新Nim游戏_线性基+博弈论 Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作 ...

  9. (博弈论)51NOD 1069 Nim游戏

    有N堆石子.A B两个人轮流拿,A先拿.每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N及每堆石子的数量,问最后 ...

随机推荐

  1. [0] 分析 EntityName 时出错。 行 2,位置 *。

    1. 报错内容“若要在加载设计器前避免可能发生的数据丢失,必须纠正以下错误: ”   “分析 EntityName 时出错. 行 2,位置 *.” 2. 如图: 3. 解决方案:查看项目全路径,是否有 ...

  2. Vue按需加载提升用户体验

    Vue官方文档异步组件: 在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载.为了让事情更简单, Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义.Vue.js 只在组 ...

  3. 盒子模型,定位技术,负边距,html5 新增标签

    盒子模型 /*[margin 外边距] margin属性最多四个 1.只写一个值,四个方向的margin均为这个值 2.写两个值:上,右两个方向,下默认=上,右 默认=左 3.写三个值:上.右.下三个 ...

  4. CentOS下安装php的mbstring扩展

    php的mbstring扩展如果没有安装会导致一些问题: 例1:登陆phpMyAdmin的时候会提示没字符串编码和字符串处理库 php_mbstring,有些程序中会用到mb_substr函数没有ph ...

  5. 【Android Developers Training】 101. 显示快速联系人挂件(Quick Contact Badge)

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. 微信小程序的开发环境搭建(Windows版本)

    前言: 小程序是指微信公众平台小程序,小程序可以帮助开发者快速的开发小程序,小程序可以在微信内被便捷地获取和传播:是一种不需要下载安装即可使用的应用小程序,和原有的三种公众号是并行的体系.2017年1 ...

  7. Ext 常用组件解析

    Ext 常用组件解析 Panel 定义&常用属性 //1.使用initComponent Ext.define('MySecurity.view.resource.ResourcePanel' ...

  8. jQuery从入门到忘记

    jQuery 是一套Javascript脚本库,注意 jQuery 是脚本库,而不是脚本框架."库"不等于"框架".jQuery 并不能帮助我们解决脚本的引用管 ...

  9. Python基础入门教程,Python学习路线图

    给大家整理的这套python学习路线图,按照此教程一步步的学习来,肯定会对python有更深刻的认识.或许可以喜欢上python这个易学,精简,开源的语言.此套教程,不但有视频教程,还有源码分享,让大 ...

  10. C#工作笔记

    没想到一个Java后端开发还要负责C#桌面程序,我感觉有点方.不过方归方,活还是要干的.简单记录下学到的一些知识点. 1.引用API函数 namespace Demo { class MyUtil { ...