前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >尼姆博弈(Nim Game)

尼姆博弈(Nim Game)

作者头像
mathor
发布2018-06-22 10:15:54
6480
发布2018-06-22 10:15:54
举报
文章被收录于专栏:mathormathor

简述

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

分析

这游戏看上去有些复杂,我们先从简单情况开始研究,如果轮到你时,只剩下一堆石子,那么此时必胜策略肯定是把这堆石子全部拿完,然后对手没有石子拿就输了;如果剩下两堆不相等的石子,必胜策略是通过取多的一堆石子将两堆石子变得相等,之后对手如果在某一堆拿若干颗,你就在另一堆拿同样多的数量,直至胜利;但是如果还剩三堆,应该怎么分析呢?假设有三堆石子(a,b,c),我们前面说到,如果只有两堆石子,并且石子数量满足(n,n),谁先手谁就输。其实我们可以把三堆石子问题转换成两堆,只要满足状态(0,n,n)并且此时是对方先手,那我方按照两堆石子的取法,就能获胜。对于这种(0,n,n)的局势,我们称为奇异局势。对任何奇异局势(a,b,c)都有a^b^c=0(^表示异或),如果我们面对非奇异局势,要如何变为奇异局势呢?假设a<b<c,我们只要将c变为a^b即可。道理很简单,因为a^b^(a^b)=0。要将c变为a^b也很简单,只要从c中减去c-a^b即可

例(14,21,39),14^21=27,39-27=12,所以从39中拿走12个,即可变成奇异局势(14,21.27)

例题

    1.HDU1849 Rabbit and Grass

思路:将输入的值存在数组中,然后连续求异或(0对任意数异或都得任意数本身)

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int m;
    int a[1001];
    while(cin>>m&&m)
    {
        int res = 0;
        memset(a,0,sizeof(a));
        for(int i = 0;i < m;i++)
        {
            cin>>a[i];
            res ^= a[i];
        }
        if(res == 0)
            cout<<"Grass Win!"<<endl;
        else
            cout<<"Rabbit Win!"<<endl;
    }
    return 0;
}

参考文章:https://hrbust-acm-team.gitbooks.io/acm-book/content/game_theory/nimbo_yi.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档