博弈论---Nim游戏(公平组合游戏,概念,证明异或为0就是必败态,示例)

目录

概念:

公平组合游戏ICG

有向图游戏

Nim游戏

先手)必胜状态

先手)必败状态

如何确定先手是否必胜或者必败(都采用最优策略)

证明:全部异或为0则是必败状态

综上:

例子


概念:

公平组合游戏ICG

若一个游戏满足:

1.由两名玩家交替行动;

2.在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关;

3.不能行动的玩家判负;

则称该游戏为一个公平组合游戏。

NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。

有向图游戏

给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负,该游戏被称为有向图游戏。

任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并且从每个局面向沿着合法行动能够到达的下一个局面连有向边。

Nim游戏

NIm就是一种公平组合游戏。

Nim游戏是一个古老的数学游戏,通常由两名玩家轮流进行。游戏使用一堆物品,例如棋子、石头或者硬币,这些物品被分成几堆,每堆可以有任意数量的物品。玩家在每一回合可以选择一堆物品,并且从中取走任意数量的物品,但是至少要取走一个。最后取走最后一个物品的玩家获胜。

Nim游戏的关键在于掌握取物品的策略,因为有正确的方法可以确保你获胜,无论对手怎么移动。这个策略涉及到让每一堆物品的数量保持在特定的模式,这样你就可以控制游戏的走向,迫使对手进入必败局面。

Nim游戏可以有很多变种和扩展,包括多堆物品、多个玩家或者其他规则的变化。

先手)必胜状态

先手进行某一个操作,留给后手是一个必败状态 时,对于先手来说是一个必胜状态 。即先手可以走到某一个必败状态。

先手)必败状态

先手不管使用什么策略,都只留给后手必胜的状态。

如何确定先手是否必胜或者必败(都采用最优策略)

我们使用异或(XOR)运算来确定每一堆物品的数量。

  1. 如果所有堆物品的数量进行异或结果为0,则这是一个必败状态。
  2. 否则,是一个必胜状态。
证明:全部异或为0则是必败状态

分情况讨论:

1.当所有堆的物品数目都为 ,

2.当前存在

证明,一定可以通过某种方式(减少某些物品的数量)使得情况2的异或值变为 。

假如 的二进制表示中最高的一位 在第 位。

那么意味着 中必然至少存在一个数 , 的第 位的值是 。

那么 , 是合法的 。

现在将拿走 中 数量的东西,则 。

拿走之后所有堆的物品数目再进行异或:

证明完成。

3.当前

证明,不管证明去拿多少数目 ,剩下的所有数异或值都不是0。

反证:假设拿出 中 个数目,剩余 ,剩下所有数的异或值为 。

则有 ①

原有 ②

再将 ① 和 ② 者进行异或运行,相同的数就被抵消掉,剩余

,与假设矛盾。证明完成

综上:

当全是0的时候,那么先手必输。

如果当前先手中数目异或不为 ,那么可以取出某个数的值使得轮到后手时,手中数目异或值为 。后手不管怎么拿,再次轮到先手时,异或值都不会为 。保证了先手始终 异或不为 的状态,而后手始终为 的状态,最后后手会首先遇到全 状态,先手始终处于必胜态。

如果先手一开始 异或值就为 ,那么后手可以始终保持最优策略使得先手 异或为 ,先手处于必败态。

K-Nim游戏:每次只能取k个

例子

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

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

输入格式

第一行包含整数 n。

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

输出格式

如果先手方必胜,则输出 Yes。

否则,输出 No。

数据范围

1≤n≤10^5,

1≤每堆石子数≤10^9

输入样例:

复制代码
2
2 3

输出样例:

复制代码
Yes
java 复制代码
import java.io.*;

class Main{
    static int n;
    public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(in.readLine());
        String[] s = in.readLine().split(" ");

        int res = 0;
        for(int i=0;i<n;i++)
            res ^= Integer.parseInt(s[i]);

        if(res==0) System.out.println("No");
        else System.out.println("Yes");
    }
}

后续会更新更多版本的Nim游戏。

相关推荐
天天被压力24 分钟前
【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #02】涨停跌停与特色股池:5类股池接口一次拉全
java·人工智能·python
斯维赤34 分钟前
从 @Tool 到 Agent 流水线:LangChain4j 进阶教学,一个库打全套
java·后端
SimonKing1 小时前
SSE项目`nexus-sse`持续优化,不一样的视觉效果
java·后端·程序员
斑鸠喳喳1 小时前
读写锁模式 Read-Write Lock
java·后端
释厄6231 小时前
多黑洞具现论·物理/生物/金融三域显化·虚拟宇宙黑洞·奇点=0 圆圈
开发语言·数据结构·人工智能·程序人生·安全威胁分析
信誓旦旦的程序猿1 小时前
【Python 量化取数指南 #09】Python 拿港股通数据:港股通成交与港股财报实测
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
小程序设计2 小时前
本科毕设避坑|大数据 / 单片机物联网 / 网络工程 / PLC / 机械设计选题与落地心得
java·hive·hadoop·单片机
UIU1142 小时前
递归算法与汉诺塔
c++·学习·算法·c#·递归
卓怡学长2 小时前
w206基于SpringBoot的社区团购小程序设计与实现
java·spring boot·spring·intellij-idea
IT枫斗者枫哥7 小时前
MyBatis一对多分页:LIMIT 20,为什么凑不齐20个订单?
java·数据库