【ACM博弈论】SG函数入门(1):从巴什博奕到尼姆游戏

在我小时候以前做题的时候,遇到博弈题往往都是漫无目的地打表找规律,或者找一些特殊情况但是没有很好的分析方法。

其实博弈题是有比较套路的解题方法的,那就是利用SG函数,第一节不会讲到SG函数的具体用法,我们先来博弈入个门,学习一下最基本的博弈类型:Nim游戏

? 作者:Eriktse
? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?
? 阅读原文获得更好阅读体验:https://www.eriktse.com/algorithm/1110.html

巴什博奕

在进入Nim游戏之前,我们先看一个简单的博弈:巴什博奕

看这道例题:http://acm.hdu.edu.cn/showproblem.php?pid=1846

由于HDUOJ经常打不开,我这里复制一下题意:

1、 本游戏是一个二人游戏;
2、 有一堆石子一共有n个;
3、 两人轮流进行;
4、 每走一步可以取走1…m个石子;
5、 最先取光石子的一方为胜;
如果游戏的双方使用的都是最优策略,请输出哪个人能赢。

假设此时的n = 10, m = 3,我们来分析一下这个局面。

我们设一个布尔函数f(x),表示当n = x时的输赢。

  • f(0) = 0,因为无法继续操作了,显然是0,也就是说这是一个必败态。
  • f(1) = 1,可以取走一个石子,使对手陷入必败态,所以这是一个必胜态。
  • f(2) = 1,可以取走两个。
  • f(3) = 1,可以取走三个。
  • f(4) = 0,无论取走一个、两个或三个都必然使得对手进入必胜态,所以这是一个必败态。
  • f(5) = 1
  • f(6) = 1
  • f(7) = 1
  • f(8) = 0,无论取走一个、两个或三个都必然使得对手进入必胜态,所以这是一个必败态。
  • f(9) = 1
  • f(10) = 1

至此,我们得到了答案,f(n) = f(10) = 1所以先手必胜,不难发现上面这个函数f(x)的规律,仅当x % 4 == 0时为0,其余情况都为1

于是我们只需要判断n % (m + 1)是否为0就能判断先手是否获胜。

这就是巴什博奕模型,是不是很简单,我们简单打个表就找到了规律。

Nim游戏

依然看这道例题:https://www.luogu.com.cn/problem/P2197

我们这么分析:

败局一定是全为0的情况,此时所有数字的异或和为0(不知道怎么写异或和的latex,大家凑合着看):

\[\oplus_{i=1}^{n}a_i = 0
\]

那么想一下那些状态可以到这个败局呢?我们反向的思考,往任意一个位置加上一个数字,就可以作为前一个状态,也就是一个必胜态(因为那个状态必然可以到达败局的状态)。

往任意一个位置加上一个数字之后就必然有:

\[\oplus_{i=1}^{n}a_i \ne 0
\]

再想一下,从一个异或和不为0的状态,是否一定有办法转移到一个异或和为0的状态。

不难发现是一定可以的。

举个栗子:

我们有4堆石子,数量分别为:1 7 2 6。这是我随便写的一个数据。

它们的异或和为:1 ^ 7 ^ 2 ^ 6 = (0 1 0),那么我可以通过调整2 -> 0使得异或和为0,现在有1 ^ 7 ^ 0 ^ 6 = 0,当然我还可以通过6 -> 4,异或和结果也是0。

不难发现,只需要从数组中找一个最高非零位大于等于异或的结果的最高非零位的数字,然后减少一部分就可以,这样的数是一定存在的。

那么也就是说任意一个异或和非零的状态都可以通过一步转移到异或和为0的状态,任意一个异或和为0的状态不管怎么走一步,都必然转移到异或和非0的状态

而石子的个数是一直减小的,最终一定会走到全0,异或和为0的状态且一定是败局。

也就是说:

必胜态W(win):异或和非0;
必败态L(lose):异或和为0;

以上就是Nim游戏模型,当然你也可以叫他Nim博弈

这一节先了解这些,下一节将会讲解SG函数的转移和子游戏的合并。

? 本文由eriktse原创,创作不易,如果对您有帮助,欢迎小伙伴们点赞?、收藏⭐、留言?

原文链接:https://www.cnblogs.com/eriktse/p/17302621.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:【ACM博弈论】SG函数入门(1):从巴什博奕到尼姆游戏 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • C#数据结构之堆栈(Stack)实例详解

    C#数据结构之堆栈(Stack)实例详解 在编程中,我们经常需要保存一些数据,这些数据可以根据其进入的先后顺序以及其他规则进行处理和访问。其中,堆栈(Stack)是一种简单但是非常有用的数据结构。本文将为大家详细讲解堆栈(Stack)的概念、用法以及C#中的实现方法。 堆栈(Stack)概述 堆栈(Stack)是一种后进先出(LIFO)的数据结构。也就是说,…

    数据结构 2023年5月17日
    00
  • C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解

    C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解 什么是顺序表 顺序表是一种线性表,它通过一块连续的存储空间来存储数据。顺序表中的数据元素排列在物理存储空间上也是连续的,每个元素占用一个固定的位置和大小,并且使用下标来访问。 顺序表的定义 下面是以int类型为例的一个简单顺序表的定义: #define SIZE 50 typedef struct { …

    数据结构 2023年5月17日
    00
  • React前端解链表数据结构示例详解

    我将为您详细讲解“React前端解链表数据结构示例详解”的完整攻略。 React前端解链表数据结构示例详解 一、前置知识 在学习本篇文章之前,您需要掌握以下前置知识: 基本的 JavaScript 语法 React 中的组件概念和生命周期 链表数据结构的基本概念和操作方法 如果您对以上知识点还不是很熟悉,可以先自学相关知识再来阅读本文。 二、链表数据结构简介…

    数据结构 2023年5月17日
    00
  • python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)

    Python实现鸢尾花三种聚类算法(K-means, AGNES, DBScan) 1. 简介 聚类是一种无监督学习算法,它将相似的数据点分组到同一个簇中。本文将介绍如何使用Python实现三种聚类算法:K-means、AGNES和DBScan,并使用鸢尾花数据集进行演示。 2. 数据集 我们将使用鸢尾花数据集来演示如何使用聚类算法。该数据集包含150个样本…

    python 2023年5月14日
    00
  • Python实现的数据结构与算法之快速排序详解

    下面是关于“Python实现的数据结构与算法之快速排序详解”的完整攻略。 1. 快速排序算法概述 快速排序是一种高效的排序算法,它的基本思想是通过分治的想将一个大问题解成多个小问题,后递归地解决这些小问题。快速排序的复杂度为O(nlogn),是一种非高的排序算法。 2 快速排序算法实现 下面使用Python实现快速排序的代码: def quick_sort(…

    python 2023年5月13日
    00
  • python最小生成树kruskal与prim算法详解

    Python最小生成树Kruskal与Prim算法详解 最小生成树是一种常用的图论问题,用于在一个加权无向图中找到一棵生成树,使得树上所有边的权值之和最小。本文将详细讲解Python实现最小生成树Kruskal与Prim算法的整个攻略,包括算法原理、实现过程和示例。 算法原理 Kruskal算法 Kruskal算法是一种基于贪心策略的最小生成树算法,其基本思…

    python 2023年5月14日
    00
  • 【ACM算法竞赛日常训练】DAY16【奇♂妙拆分】【区区区间间间】【小AA的数列】数学 | 位运算 | 前缀和

    DAY16共3题: 奇♂妙拆分(简单数学) 区区区间间间(单调栈) 小AA的数列(位运算dp) ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 阅读原文获得更好阅读体验:https://www.eriktse.com…

    算法与数据结构 2023年4月20日
    00
  • python实现五子棋算法

    下面是关于“Python实现五子棋算法”的完整攻略。 1. 五子棋算法简介 五子棋是一种双人对弈的纯策略型棋类游戏,通常在15×15的棋盘上进行。子棋的目标是在棋盘上先形成一条连续的、由相同颜色的棋子组成的直线,即五子连,获得胜利。 2. Python实现五子棋算法 2.1 算法流程 五子棋算法的流程如下: 初始化棋盘,括棋盘大小、棋子颜色等。 玩家落子,即…

    python 2023年5月13日
    00
合作推广
合作推广
分享本页
返回顶部