「博弈论:巴什+威佐夫+nim游戏」学习笔记

未经允许,请勿转载。

博弈论有好多好多好多..

整理一下我来写关于巴什博弈,威佐夫博弈+nim游戏

首先先写一些名词:

必败态:即奇异局势,面对这种局势必败。

必胜态:通过合理操作可以变成必胜局。

1.巴什博弈

题面:Alice 和 Bob 玩取石子游戏。他们的游戏是这样的:总共有 n 个石头,每个人每次可以取 1 到 m 个石头,不能不取。最后取完的人获胜。现在Alice 先取,假设双方都采取最好的策略,告诉你 n 和 m,问他是否能赢,如果能,第一次要取几个。

这道题应该算最早接触的博弈,在小学数学课本上的玩意儿。

这题其实就是判断\(n\)是否为\((m+1)\)

如果先手取\(1\),那么后手可以取\(m\).

如果先手取\(2\),那么后手可以取\(m-1\).

如果先手取\(3\),那么后手可以取\(m-2\).

....

如果先手取\(m\),那么后手可以取\(1\).

这一样,无论先手取什么,后手都可以将其维护为\(m+1\)

很明显,如果\(n\)\((m+1)\)的倍数,那么先手必败

若不是倍数,则先手可以先取\(n\)%\((m+1)\)个,这样,剩下来的石子就为\((m+1)\)的倍数,那么后手无论取几,先手都可以维护为\((m+1)\)个,那么先手必胜

代码:

#include <iostream>
#include <cstdio>
using namespace std;
int n,m;
int main()
{	
	cin>>n>>m;
	if(n%(m+1)==0)
		cout<<"No";
	if(n%(m+1)!=0)
		cout<<"Yes"<<endl<<n%(m+1);
	return 0;
} 

2.威佐夫博弈

先放上题面:

Alice和Bob玩取石子游戏。他们的游戏是这样的:有两堆数量为 a 和 b 的石头。游戏开始两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两 堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到 Alice 先取,假设双方都采取最好的策略,问最后 Alice 是胜者还是败者。

\(b>a\)

\(k=b-a,t=(1+\sqrt{5}\)))

if\(([k*t]==a)\)先手败

else 后手败

状态(奇异局势)\((0,0)(1,2)(3,5)(4,7)(6,10)(8,13)(9,15)(11,18)(12,20)\)...都是先手败

差分别为\(0,1,2,3,4,5,6,7,8....\)

因此判断\(a,b\)的差是否符合上面奇异局势即可

对于奇异局势,有如下公式:

\(a[i]=[i*(1+\sqrt{5})/2],b[i]=a[i]+i\)。(\(k=0,1,2\)..,[]表示取整)

其中,可以判断\(i\)\(a\),\(b\)的差,即是k

那判断\([k*(1+\sqrt{5})/2)]\)是否为a即可

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{	int a,b,t,k;
	while(cin>>a>>b)
	{	if(a>b){t=a;a=b;b=t;}
		int k=b-a;
		if(int(k*(1+sqrt(5))/2)==a)printf("0\n");
		else printf("1\n");
	}
	return 0;
}

3.nim游戏

写这题前先放上异或性质:

1^1=0
0^0=0
1^0=1
A^0=A
A^A=0
A^B^A=A^A^B=0^B=B

丢上题面

甲,乙两个人玩Nim取石子游戏。
nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这n堆石子的数量,他想知道是否存在先手必胜的策略。

这题好神奇的。

设这些堆分别为:\(a_1,a_2,a_3...a_n\)

\(a_1\)$a_2$\(a_3\)...\(a_{n-1}\)^\(a_n==0\)则先手败

否则先手胜。

证明一下叭:

首先,若所有都为\(0\),那么\(0\)$0$\(0\)...^\(0=0\)

否则:

这些堆当中设所有的异或和为\(k\)。设\(k\)的最高位为\(i\),那么一定有个数第\(i\)位是\(1\),而假设这就是\(a_1\)。再设除了\(a_1\)其他的异或和为\(x\),则:\(a_1\)^\(x=k\)。且\(x\)没有第\(i\)位。

然后把\(a_1\)^\(k\)

这时,\(a_1\)$k$\(x\)=\(a_1\)$x$\(k=k\)^\(k=0\)

若这时\(k=0\),那么怎么变动都不可能异或和为\(0\)了。

\(pia\)上代码

#include<iostream>
#include<cstdio>
using namespace std;
int T,n,x;
int main()
{	scanf("%d",&T);
    while(T--)
    {	int ans=0;
        scanf("%d",&n);
        while(n--)
        {	scanf("%d",&x);
            ans^=x;
        }
        if(!ans)printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}

阶梯nim

送上题面先:

有n个位置1...n,每个位置上有ai个石子。有两个人轮流操作。操作步骤是:挑选1...n中任一一个存在石子的位置i,将至少1个石子移动至i−1位置(也就是最后所有石子都堆在在0这个位置)。谁不能操作谁输。求先手必胜还是必败。

其实这个结果只跟奇数阶梯上的石子有关。

如果先手把偶数阶梯的若干石子往下移,那么后手也会相应把这堆石子继续往下移,直到\(0\),然鹅这样并不会改变什么,只会改变石子的数量。

如果先手吧奇数阶梯的若干石子往下移,那么当这堆石子到\(0\)的位置时,变成之前的后手先移其他的了。

所以,这题只要把奇数阶梯上的石子走一遍nim即可。

by Rainy7

posted @ 2020-01-31 18:32  Rainy7  阅读(329)  评论(0编辑  收藏  举报