Nim游戏算法介绍

周周给大家简单介绍一下基础nim博弈游戏原理以及代码实现。

我们先来了解一下公平组合游戏,它满足:1.两名玩家交替进行。2.在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关。3.不能移动的玩家判负。

nim游戏属于公平组合游戏,来看到一道例题:给定n堆石子,两位玩家轮流操作,每次可以从任意一堆石子中取出任意数量的石子,最后算无法操作的人失败。

原理分析:我们先来看一个最简单的样例,假如有两堆石子,一堆2个石子,另一堆3个石子,此时甲先手,甲可以先拿走1个石子,共有2堆石子,每堆都有2个石子,此时不管乙从哪堆拿多少个石子,甲都可以镜像得从另一堆中拿走多少个石子,甲拿走了最后的石子,最终乙会没有石子拿,则甲先手赢得比赛。我们可以理解先手的必胜状态:可以走到一个必败状态,先手的必胜状态则是走不到任何一个必败状态。

以上是方便理解,针对一般问题我们有一个定理。如果有n堆石子,每堆有a1,a2,a3,a4,a5,a6.....an

个,如果a1^a2^a3^a4^a5......^an=0(先手必败),如果a1^a2^a3^a4^a5......^an!=0(先手必胜)这是一个定理,大家现有初步理解,再进行证明。(在这里补充一个简单异或运算,方便理解上面定理,异或运算符为^,运算规则:0^0=0;  0^1=1;  1^0=1;   1^1=0;即:参加运算的两个对象,如果两个位为“异”(值不同),则该位结果为1,否则为0。例如:3^5 =  0000 0011 | 0000 0101 =0000 0110,因此,3^5 = 6)

我们来分析一波。

第一种情况:每堆石子都为0时,此时0^0^0^0^……^0=0,即不能进行任何操作时异或值为0。

第二种情况:当前a1^a2^a3^a4……^an=x!=0时,一定可以通过某种方式使他们的异或值为0,即从某一堆中拿走一部分石子,使剩下的数异或值为0。证明:假设x的最高一位1在第k位,则必有a1到an中必存在一个数ai,ai的第k位是1.(反证法:假如所有数的第k位都是0的话,则x的第k位也必然是0,故以上结论成立)显然ai^x<ai,(例:ai:10010001,已知1^1=0,故ai^x=10000000

                                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​       x:      10001)

则ai-(ai^x)>0恒成立,我们从ai中拿走ai-(ai^x)个石子后,还剩ai-(ai-(ai^x))=ai^x个石子,则

a1^a2^a3^a4…^ai^x…^an=x^x=0,即就可说明,剩下的数异或值为0时,走到一个必败状态,先手必赢。

第三种情况:当前a1^a2^a3^a4……^an=0时,不管怎么去拿,剩下的数的异或值一定不是0,这里可以用反证法来证明:此时从ai堆中拿出一部分石子,假设ai变成了ai',假设有a1^a2^a3^a4……^ai'^ai+1……an=0,把前面两个式子异或起来显然得到ai^ai'=0,即ai=ai'是不成立的,所以我们可以得到先手不管怎么拿,走不到任何一个必败状态,先手必输。

总结以上几种情况我们可以理解为一开始所有数的异或值为0时,先手不管怎么去拿,后手去拿时所有数的异或值一定不为0,则先手去拿时异或值一定为0,先手不管怎么拿,走不到任何一个必败状态,先手必输。一开始所有数的异或值不为0时,同理。

周周萌新一枚,自学过后帮大家总结,可能有瑕疵,欢迎指正。

下面看一下代码实现:

#include <stdio.h>
#include <algorithm>

using namespace std;

int main(){
	int n;
	int res=0;
	
	scanf("%d",&n);
	while(n--)
	{
		int x;
		scanf("%d",&x);
		res^=x;
	}
	
	if(res)puts("Yes");
	else puts("No");
	
	return 0;
}

这只是非常基础的博弈论知识,用异或运算实现的思想还要不断去思考才能真正理解。希望对大家有帮助。
 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值