zoukankan      html  css  js  c++  java
  • Nim游戏——简单博弈论

    原题链接
    给定n堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。

    问如果两人都采用最优策略,先手是否必胜。

    输入格式
    第一行包含整数n。

    第二行包含n个数字,其中第 i 个数字表示第 i 堆石子的数量。

    输出格式
    如果先手方必胜,则输出“Yes”。

    否则,输出“No”。

    数据范围
    1≤n≤105,
    1≤每堆石子数≤109
    输入样例:
    2
    2 3
    输出样例:
    Yes

    先上一波代码

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int n;
    	int res=0;
    	cin>>n;
    	while(n--){
    		int x;
    		cin>>x;
    		res^=x;
    	}
    	if(res) cout<<"Yes"<<endl;
    	else cout<<"No"<<endl;
    	
    	return 0;
    } 
    

    该题为简单的 博弈论题目,一般博弈论题目有如下特征:

    1.有两名选手;

    2.两名选手交替操作,每次一步,每步都是在有限的合法集合中选取一种进行;

    3.在任何情况下,合法操作只取决于情况本身,与选手无关;

    4.游戏的败北条件为:当某位选手需要进行操作时,当前没有任何可以执行的合法操作,则该选手败北。

    先来介绍Nim里的两种状态,先手必败状态和先手必胜状态。
    前者是先手走不到任何一个必败状态,即后手无法是必败状态,先手必败。
    后者即先手可以走到某个必败状态,此时为后手操作,后手必败。
    

    Nim游戏中有个经典结论:若a1^a2…an==0 则先手必败。

    我们可以从简单的数据入手,比如有两堆石子的数量分别为2、3。那么是不是先手必胜呢。我们可以先用结论及代码验证一下。

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int a1 = 2 , a2 = 3 ;
    	if(a1^a2==0) puts("Win");
    	else puts("Lose");
    	return 0;
    }
    

    运行结果如图
    在这里插入图片描述
    那么我们现在可以模拟一下具体过程,前提是每个人每一步都是最优策略。先手从石子数为3的堆里取走一个石子,此时变为2 2,接下来不论后手做任何操作,先手只需在另一堆石子里做相同的操作,这样就再次使得两堆石子的数目一样。如此循环下去,一定是后手遇到必败状态,先手胜利。
    接下来进行简单的证明一下:
    首先,当所有的堆的石子数均为0时,异或值也是0,即不能进行任何操作,先手必败。
    然后,如果异或值不为零,即a1^a2…an= k(k为非零常数),先手一定可以某种操作(即从某堆石子中拿走部分石子)让异或值变为0,此时后手走到了必败态,先手必胜。(具体为什么是异或值还有待探索)
    假设k的二进制表示中最高的一位1是第x位, 那么在a1-an中必存在有一个数ai的第x位是1;那么ai^x<ai(ai的第k位由1变为0),我们可以从ai个石子中拿走ai-ai ^x 个石子(操作一定合法),这样的话所有的数的异或值就是0。
    最后,我们来证明如果a1^a2…an=0,无论如何拿,所有数的异或值一定不是0。反证法可证。

    具体为什么是异或值为0,可以参考K-Nim游戏;

    Nim还有很多变形,学习中。
    扔一道台阶Nim的题吧 惊奇队长和灭霸的决战 来自临沂大学新生赛
    蓝桥杯历年试题 高僧斗法 也是如此
    最后放一篇写的很好的高僧斗法的题解

    不当之处,请多指教。

  • 相关阅读:
    mysql中文乱码
    阻止保存要求重新创建表的更改
    PowerDesigner连接数据库(Oracle)
    PowerDesigner连接数据库(SqlServer)
    Environment Variable: "PATH" 失败
    pl/sql查看锁表及解锁
    Oracle将误闪的数据认回到指定的时间段
    内存监测2
    Windows常用的一些DOC命令
    何为序列化
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853225.html
Copyright © 2011-2022 走看看