【博弈】一些简单的博弈

下面总结了一些简单的博弈题目:

1、有一堆石子共有n个,A和B轮流取,A先,每次最少取1个,最多取m个,先取完者胜,A,B足够聪明,问谁先胜?(巴什博奕

思路:显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。

所以若n%(m+1)!=0,A胜,否则B胜。

这个游戏还可以有一种变相的玩法:两个人轮流报数,每次至少报一个,最多报十个,谁能报到100者胜。

100=(10+1)*9+1,对应上述方法解答即可。

对于巴什博弈,那么我们规定,如果最后取光者输,那么又会如何呢?
(n-1)%(m+1)==0则后手胜利
先手会重新决定策略,所以不是简单的相反能行的。

例:

n=16  m=4

无论先手怎么取,后手始终可以取到(m+1)*t+1(t是整数)

第一次先手取后:后手取到n=11

第二次先手取后:后手取到n=6

第三次先手取后:后手取到n=1

所以先手败。

而(16-1)%(4+1)==0成立

而当 (n-1)%(m+1)!=0时,先手可以将状态取到对自己有利的状态。

例:

n=17 m=4

先手取1,使n=16,当前局面变成上述例子的局面。所以先手胜利。


2、n个石子摆成一圈,A和B轮流取,每次可以从中取一个或相邻两个,先取完者胜,A先取,问谁胜?(始终让剩下的棋子对称)

 若n==1||n==2 则A胜,否则B胜

3、 有n堆石子,每堆石子都有任意个,A和B轮流从取任意堆里取一定的石子,每次只能从一堆里至少取一个,A先取,先取完者胜,问谁胜?(Nimm博弈)

将n个数异或一遍,若不为0,则A胜,否则B胜

4、n堆石子,2人博弈.每次选择一堆石子,移除至少一个(可以是任意多个)后,将剩下的任意分配(当然也可以什么都不做),2人轮流操作,不能操作者输.求先手必胜还是必败?

 解:如果只有一堆石子,则先手必胜.如果有两堆相同数目的石子,显然先手必败,因为对手只需对称操作即可.同理可知,如果石子可分为两组,对应堆石子数相等,如{1,2,3,1,2,3},则先手同样必败,于是数目相同的两堆先可以暂不考虑.如果有两堆数目不同的石子,则先手可以使之数目相同,先手必胜.如果有三堆互不相同的石子,先手可以选择最大的一堆操作,移除一部分后,使剩下的石子正好补齐剩下两堆之间的差距,先手必胜.依次类推,先手必败当且仅当初始时石子数是{1,2,3,1,2,3}这种类型。

所以,要做的就是判断出现的石子数类型是否是偶数,当所有类型都是偶数时,说明石子是可以对称的。那么先手必败,反之,先手必胜

链接:https://www.nowcoder.net/acm/contest/75/F
来源:牛客网

共有N堆石子,已知每堆中石子的数量,两个人轮流取石子,每次只能选择N堆石子中的一堆取一定数量的石子(最少取一个),取过子之后,还可以将该堆石子中剩余的石子随意选取几个放到其它的任意一堆或几堆上。等哪个人无法取子时就表示此人输掉了游戏。注意:一堆石子没有子之后,就不能再往此处放石子了。

假设每次都是小牛先取石子,并且游戏双方都绝对聪明,现在给你石子的堆数、每堆石子的数量,请判断出小牛能否获胜。

//链接:https://www.nowcoder.net/acm/contest/75/F
//来源:牛客网
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	int N;
	int a[101];
	while (cin >> N&&N)
	{
		memset(a, 0, sizeof(a));
		int t;
		for (int i = 0; i < N; i++)
		{
			cin >> t;
			a[t]++;
		}
		int flag=0;
		for (int i = 0; i < 101; i++)
		{
			if (a[i] % 2 != 0)
			{
				flag = 1;
				break;
			}
		}
		if (flag)
			cout << "Win" << endl;
		else
			cout << "Lose" << endl;
	}

	system("pause");
	return 0;
}

5、有一堆石子,A和B轮流从中取一定的石子,但规定:第一次不能取完,至少一个;从第二次开始,每个人取的石子数至少为1,至多为对手刚取的石子数的两倍。A先取,问A是否会胜?

结论:若其对应的石子数目刚好是斐波那契数,则A必败,否则A必胜。(斐波拉契博弈

链接:https://www.nowcoder.com/acm/contest/77/G
来源:牛客网

题目描述

    幼儿园开学了,为了让小盆友们能尽可能的多的享受假期。校长大人决定让小盆友分批到校,至于每批学生来多少人由一个小傻子和一个小仙女负责,两个人轮番负责,校长会在最后的时候去查看工作进度,小傻子不想被别人嘲笑自己傻,小仙女要证明自己比小傻子聪明。所以她们回去争抢安排最后一名小盆友。每次安排的小盆友至少为1,至多为上一次安排的2倍。小仙女抢到了先手的机会。第一次安排小盆友不能直接安排所有的小盆友一起回校。

输入描述:

单组测试数据
输入一个整数n——n代表小盆的个数(n>=2&&n<=1e9)

输出描述:

输出获胜人的名字——“Xian”或者“Sha”

#include <iostream>
using namespace std;

int main()
{
	int a[100];
	a[1] = 1;
	a[2] = 2;
	for (int i = 3; i < 100; i++)
		a[i] = a[i - 1] + a[i - 2];
	int n;
	cin >> n;
	for(int i=1;i<100;i++)
		if (a[i] == n)
		{
			cout << "Sha" << endl;
			return 0;
		}
	cout << "Xian" << endl;
	system("pause");
	return 0;
}


部分来自:http://blog.csdn.net/acmlzq/article/details/51212297(取石子总结)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值