• 「博弈论:巴什+威佐夫+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
    ");
    		else printf("1
    ");
    	}
    	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
    ");
            else printf("Yes
    ");
        }
        return 0;
    }
    

    阶梯nim

    送上题面先:

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

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

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

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

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

    by Rainy7

  • 相关阅读:
    共享内存:mmap函数实现
    navigationItem.rightBarButtonItem 设置背景图片,颜色更改解决的方法
    C语言基础
    easyui datagrid合并相同数据的单元格。
    js 计算总页数的最高效方式
    取消本地文件夹与SVN服务器的关联
    扩展自easyui的combo组件的下拉多选控件
    利用art.template模仿VUE 一次渲染多个模版
    利用art.template模仿VUE
    JavaScript单独的模块中传递数据
  • 原文地址:https://www.cnblogs.com/Rainy7/p/Game-theory.html
Copyright © 2020-2023  润新知