尼姆博弈

尼姆堆
【问题描述】
有3堆硬币,分别是3,4,5
二人轮流取硬币。
每人每次只能从某一堆上取任意数量。
不能弃权。
取到最后一枚硬币的为赢家。

求先取硬币一方有无必胜的招法。

题解:尼姆博弈模型,大致上是这样的:有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜。

尼姆博弈:http://blog.csdn.net/u013514928/article/details/69055286

Bouton定理:先手能够在 非平衡尼姆博弈 中取胜;而后手能够在 平衡的尼姆 博弈中取胜, 即状态(x1, x2, x3, …, xn)为P状态当且仅当x1 xor x2 xor x3 xor … xor xn =0,这样的操作也称为Nim和(Nim Sum)。
我们以一个两堆物品的尼姆博弈作为试验。设游戏开始时游戏处于非平衡状态。这样,先手就能通过一种取子方式使得他取子后留给后手的是一个平衡状态下的游戏,接着无论后手如何取子,再留给先手的一定是一个非平衡状态游戏,如此反复进行,当后手在最后一次平衡状态下取子后,先手便能一次性取走所有的物品而获胜。而如果游戏开始时游戏牌平衡状态,那根据上述方式取子,最终后手能获。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;

void solve()
{
    int a[] = {3, 4, 5};
    //2, 5, 12, 14,为不平衡态, 先手可以胜 
    //1, 2, 3, 就是平衡态,先手必输; 
    
    int n = 3;
    
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum ^= a[i];
    } 
    
    if (sum == 0)
    {
        cout << "说明为平衡态,为必输局" << endl;
    }
    
    //否则为不平衡态
    int x = 0;
    for (int i = 0; i < n; i++)
    {
        x = sum ^ a[i];
        if (x < a[i]) 
        {
            cout << a[i] << "===>" << x << endl;
        }
    } 
} 

int main()
{
    solve();
    
    return 0;
        
} 

 

 

 

 

posted @ 2018-03-20 01:13  douzujun  阅读(458)  评论(0)    收藏  举报