Java教程

Nim游戏

本文主要是介绍Nim游戏,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Nim 游戏

今天算法课要做一道Nim游戏的题,内容是这样:

冰墩墩和雪融融放置了N堆不同数目的金牌,编号1..N,第i堆中有A[i]个金牌。

每一次行动,冰墩墩和雪融融(电脑)可以选择从一堆金牌中取出任意数量的金牌。至少取1个,至多取出这一堆剩下的所有金牌。

冰墩墩和雪融融轮流行动,取走最后一个金牌的人获得胜利。

假设每一轮游戏都是冰墩墩先行动,请你判断在给定的情况下,如果双方都不会失误,谁会获得胜利?

输入:

第1行:1个整数N。表示金牌堆数。1≤N≤100

第2行:N个整数,第i个整数表示第i堆金牌的个数A[i],1≤A[i]≤10000

输出:

第1行:1个整数,若冰墩墩能够获胜输出“0",否则输出“1"

想了好久没做出来,最后去ACWING看了y总的讲解才明白,这里记录一下

先上代码:

#include "iostream"
#include "vector"
#include "algorithm"
#include "set"
#include "map"
#include "stdio.h"
#include "string"
#include "string.h"
#include "cstring"
#include "utility"
#include "bitset"
#include "stack"
#include "queue"
using namespace std;



const int N = 1110;
int A[N];
int nim (int A[],int n){
	int res = 0;
	for(int i = 1; i <= n; i++ ) {
		res ^= A[i];
	}
	return (res == 0);
}

int main(){
	int n;
	cin>>n;
	for(int i = 1; i <= n; i++ ){
		cin>>A[i];
	}
	printf("%d\n",nim(A,n));
}

再上结论:

若a1a2a3.……an = 0,则先手的必败,否则先手必胜。为什么呢?

证明过程

首先

有人拿走最后一块金牌后,每一堆的金牌数都是0,这时候a1a2a3…… = 0

然后

我们证明当 a1a2a3…… != 0 时,可以通过从一个堆中拿金牌,使a1a2a3…… = 0

若 a1a2a3…… = x != 0,那设x的二进制表示中,1的最高位为第k位,那么,a1~an中存在至少一个数如ai它的第k位是1,所以,ai^x <ai,所以我们可以拿走一些个石子,使ai 变成 ai ^x ,这时候,a1a2a3…… 变成了 a1a2a3……aix……an = x ^ x = 0

再想

若刚开始的时候,a1^a2…… != 0 ,那么先手的人,就可以拿走石子让a1a2a3…… = 0,然后下一个人不管怎么拿,都不为0,这样一直拿下去,先手拿到最后,a1~an 都为0,先手获胜.

这篇关于Nim游戏的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!