理论: 博弈3: Nim博弈
来源:互联网 发布:淘宝上的止鼾器管用吗 编辑:程序博客网 时间:2024/05/13 06:30
Nim博弈原型
个人定义:
有n堆石头, 每堆ai颗石头。 Alice和Bob分别从非空的石头堆中取走至少一颗石子。Alice先取,
取光所有的石头即为获胜。当双方都采取最优策略的时候, 谁会获胜?
严谨定义:
有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。
我们先说最终结论:
对于一个Nim游戏的局面(a1,a2,…,an),它是P-position当且仅当a1^a2^…^an=0,其中^表示异或(xor)运算。
简单的来说:
a1 ^ a2 ^ a3 ^ ………… ^an = 0; 则先手必败;
a1 ^ a2 ^ a3 ^ ………… ^an != 0; 则后手必败;
游戏的必胜策略就是:使得自己回合结束之后每组的个数取XOR = 0;
证明:
根据定义,证明一种判断position的性质的方法的正确性,只需证明三个命题: 1、这个判断将所有terminal position判为P-position;2、根据这个判断被判为N-position的局面一定可以移动到某个P-position;3、根据这个判断被判为P-position的局面无法移动到某个P-position。
第一个命题显然,terminal position只有一个,就是全0,异或仍然是0。
第二个命题,对于某个局面(a1,a2,…,an),若a1^a2^…^an!=0,一定存在某个合法的移动,将ai改变成ai’后满足a1^a2^…^ai’^…^an=0。不妨设a1^a2^…^an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的最高位那个1是怎么得到的)。这时ai^k < ai一定成立。则我们可以将ai改变成ai’=ai^k,此时a1^a2^…^ai’^…^an=a1^a2^…^an^k=0。
第三个命题,对于某个局面(a1,a2,…,an),若a1^a2^…^an=0,一定不存在某个合法的移动,将ai改变成ai’后满足a1^a2^…^ai’^…^an=0。因为异或运算满足消去率,由a1^a2^…^an=a1^a2^…^ai’^…^an可以得到ai=ai’。所以将ai改变成ai’不是一个合法的移动。证毕。
以上证明转自:http://www.cnblogs.com/exponent/articles/2141477.html
如何转换成XOR = 0的局面?:
在这里我们进行反向计算: 一直最后的XOR = 0; 在这里我们计算a1的最后的值 = 0 ^ an ^ an - 1 ^ an-2…… ^a2;
这里我们判断我们比较我们计算得到的a1的值和初始的a1的值, 如果计算得到的a1的值小于初始a1, 则a1就是目标值;
现在我们来解决一下最初的问题:
int n, a[10000];int main (void){ int x= 0; while(scanf("%d", &n) != EOF && n) { for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); x ^= a[i]; } if(x) printf("Alice!\n"); else printf("Bob!\n"); } return 0;}
Nim博弈演变(POJ 1704)
poj传送门:
题目大意:
排成直线的格子上, 放着n枚 棋子。 其中第i枚放在qi的位置。Alice和BOb轮流一个棋子向左移动。每次可以及任意多, 但是不允许反超其他棋子, 也也将两个棋子放在同一个格子内。
无法移动的一方失败, Alice先手。假设双方都取最优策略, 问谁能取胜;
分析:
我们可以将棋子移动的问题Nim博弈的问题, 按照棋子总数奇偶性和棋子的奇偶性来划分棋子, 具体情况如下所示:
现在我们来讨论
A。棋子总数为偶数:
那么我们将棋子两两一组, Nim问题中的“堆数”即为(棋子总数/ 2),每堆的堆数就是两两棋子之间的距离。现在单独分析每一对棋子。
对于右棋子的左移, 我们就可以当作从Nim博弈中的堆中取出石子, 这个符合Nim规则;
对于左棋子的左移, 在Nim博弈中就相当于在堆中增加棋子, 这对于Nim博弈是不合法的 , 但是我们可以通过将右棋子左移相同的步数而加一抵消。
通过上述分析, 我们不难发现, 对于棋子总数为偶数时, 我们可以将此问题转化为Nim博弈的问题;
B。棋子总数为奇数;
我们假设0好位置还有一枚棋子, 而将其凑成偶数枚棋子, 其他的部分不变。
综合上述两种情况, 我们不难总结出下文的流程
int n, p[1000000];int main(void){ while (scanf("%d", &n) != EOF) { for (int i = 1; i <= n; i++) scanf("%d", &p[i]); if (n % 2 == 1) p[n++] = 0; sort(p, p + n); int x = 0; for (int i = 0; i < n - 1; i += 2) x ^= (p[i + 1] - p[i] - 1); if (!x) printf("Bob will win\n"); else printf("Georgia will win\n"); } return 0;}
- 理论: 博弈3: Nim博弈
- 博弈-Nim博弈
- nim 博弈
- Nim博弈
- Nim博弈
- NIM 博弈
- Nim 博弈
- Nim博弈
- nim 博弈
- Nim博弈
- Nim博弈
- Nim博弈
- nim博弈
- nim博弈
- (博弈Nim)Nim
- 基础博弈—Nim博弈
- Northcott Game + 博弈 + nim博弈
- HDU1851(sg博弈+nim博弈)
- MATLAB随机数:重启后结果一样解决方法
- IOS and JAVA 的 RSA 加密解密
- Myeclipse 2015 stable 2.0 完美破解方法
- iOS 上传图片
- 用一颗热心,迎接生活的挑战——nginx初始
- 理论: 博弈3: Nim博弈
- zoj 2966 Build The Electric System【最小生成树 Kruskal && prim】
- 一个小小的stm32控制步进电机(28YJ)的程序
- Paxos Made Simple【翻译】
- BZOJ1191超级英雄Hero
- Class org.apache.struts2.json.JSONWriter can not access a member of class
- Instruments Tutorial with Swift: Getting Started
- 日期4
- Java初学之集合(二)