Nim游戏与阶梯Nim博弈

nim游戏

问题描述
一共有N堆石子,编号1~n,第i堆中有个a[i]个石子。
每一次操作Alice和Bob可以从任意一堆石子中取出任意数量的石子,
至少取一颗,至多取出这一堆剩下的所有石子。
两个人轮流行动,取光所有石子的一方获胜。Aice为先手.
给定a,假设两人都采用最优策略,谁会获胜?
问题分析
从简单情况分析,如果轮到你的时候,只剩下一堆石子,那么此时的必胜策略肯定是把这堆石子全部拿完一颗也不给对手剩,然后对手就输了。如果剩下两堆不相等的石子,必胜策略是通过取多的一堆的石子将两堆石子变得相等,以后如果对手在某一堆里拿若干颗,你就可以在另一堆中拿同样多的颗数,直至胜利。如果你面对的是两堆相等的石子,那么此时你是没有任何必胜策略的,反而对手可以遵循上面的策略保证必胜。
如果是三堆石子……好像很难分析了
直接说结论好了。
a1^a2^a3^......^an==0时先手输。
a1^a2^a3^......^an!=0时先手赢。

数学问题很神奇,完全没有道理的和异或运算扯上了关系。记住就好了吧。

阶梯nim博弈

问题描述

佐治亚和鲍勃决定玩一个自己发明的游戏。他们在纸上画一排网格,将网格从左到右编号1,2,3,.并在不同的网格上放置N个棋子,例如,如下图所示:

佐治亚和鲍勃轮流移动棋子。每次玩家会选择一个棋子,然后把它移到左边,而不超过任何其他棋子,或者越过左边的边缘。玩家可以自由选择棋子移动的步骤数,限制棋子必须至少移动一步,而一个网格最多只能包含一个棋子。不能移动的玩家输掉了比赛。

自从“女士优先”之后,乔治亚一直是第一名。假设佐治亚和鲍勃在比赛中都尽了最大的努力,也就是说,如果他们中的一个知道赢得比赛的方法,他或她就能做到这一点。

考虑到棋手们最初的位置,你能预测谁将最终赢得这场比赛吗?
输入

输入的第一行包含一个整数T(1<=T<=20),测试用例数。接下来是T个病例。每个测试用例包含两行。第一行由一个整数N(1<=N<=1000)组成,表示棋子的数量。第二行包含N个不同的整数P1,P2.Pn(1<=PI<=10000),这是n个棋手的初始位置。
输出量

对于每个测试用例,打印一行,“佐治亚将赢”,如果佐治亚将赢得比赛;“鲍勃会赢”,如果鲍勃将赢得比赛;否则‘不确定’。
样本输入

2
3
1 2 3
8
1 5 6 7 9 12 14 17
样本输出

Bob will win
Georgia will win

代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

void sort(int a[])
{
	int len = 0;
	int i, j, t;
	while (a[len] != 0)
	{
		len++;
	}
	for (i = 0; i < len - 1; i++)
	{
		for (j = 0; j < len - 1-i; j++)
		{
			if (a[j] > a[j + 1])
			{
				t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
		}
	}
 }
int main()
{
	int t, n;
	int arr[20][1000] = { 0 };
	int i, j;
	scanf("%d", &t);
	for (i = 0; i < t; i++)
	{
		scanf("%d", &n);
		for (j = 0; j < n; j++)
			scanf("%d", &arr[i][j]);
	}
	for (i = 0; i < t; i++)
		sort(arr[i]);
	for (i = 0; i < t; i++)
	{
		int rec = 0;
		int len = 0;
		while (arr[i][len] != 0)
		{
			len++;
		}
		if (len % 2 == 1)
		{
			for (j = 0; j < len; j = j + 2)
			{
				if (j == 0)
					rec ^= arr[i][0] - 1;
				else
					rec ^= arr[i][j] - arr[i][j - 1] - 1;
			}	
		}
		else
		{
			for (j = 1; j < len; j = j + 2)
			{
				rec ^= arr[i][j] - arr[i][j - 1] - 1;
			}
		}
		if(rec!=0)
			printf("Georgia will win\n");
		else
			printf("Bob will win\n");
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值