【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日

相关文章

  • Python实现的三层BP神经网络算法示例

    以下是关于“Python实现的三层BP神经网络算法示例”的完整攻略: 简介 BP神经网络是一种常见的人工神经网络,它可以用于分类和回归问题。本教程将介绍如何使用Python实现三层BP神经网络算法,并讨论如何使用该算法进行分类。 步骤 1.导入库和数据 首先,我们需要导入必要的库,包括numpy和pandas。在Python中,可以使用以下代码导入这些库: …

    python 2023年5月14日
    00
  • python编程实现希尔排序

    下面是关于“Python编程实现希尔排序”的完整攻略。 1. 希尔排序简介 希尔排序是一种高效的排序算法,它是插入排序的一种改进。希尔排序通过将待排序的数组分成若干个子序列,对每个子序列进行插入排序,最后再对整个数组进行一次插入排序。希尔排序的时间复杂度为$O(nlogn)$,是一种比较快速的排序算法。 2. Python实现希尔排序 下面是Python实现…

    python 2023年5月13日
    00
  • C++高级数据结构之优先队列

    C++高级数据结构之优先队列 什么是优先队列? 优先队列是一种特殊的队列,其中每个元素都有一个优先级。当加入一个元素时,它会被放置在队列中的适当位置,以确保优先级最高的元素位于队头。从队列中取出元素时,总是从队头删除元素。 优先队列的应用 优先队列的常见应用场景包括: 操作系统任务调度 网络传输协议TCP中的拥塞控制算法 各种图像算法如边缘检测等 C++中S…

    数据结构 2023年5月17日
    00
  • java数据结构与算法数组模拟队列示例详解

    下面是“java数据结构与算法数组模拟队列示例详解”的完整攻略。 标题 Java数据结构与算法:数组模拟队列示例详解 简介 本文将以Java语言为例,详细讲解如何使用数组模拟队列。对于初学者来说,队列是一个非常基础的数据结构,掌握其实现方法可以帮助进一步理解其他的数据结构和算法。 队列的定义 队列(Queue)是一种先进先出(First In First O…

    数据结构 2023年5月17日
    00
  • AtCoder Beginner Contest 300

    A – N-choice question (abc300 a) 题目大意 给定一个元素互不相同的数组\(c\)和 \(a,b\),找到 \(i\)使得 \(c_i = a + b\) 解题思路 直接for循环寻找即可。 神奇的代码 #include <bits/stdc++.h> using namespace std; using LL = …

    算法与数据结构 2023年4月30日
    00
  • Python算法应用实战之栈详解

    Python算法应用实战之栈详解 什么是栈? 栈是一种常用的数据结构,它具有后进先出(LIFO)的特点。栈的基本操作包括入栈、出栈、获取栈元素和判断栈是否为空。 Python实现栈的过程 在Python中,可以使用列表来实现栈。以下是使用列表实现栈的示例代码: class Stack: def __init__(self): self.items = [] …

    python 2023年5月13日
    00
  • Python实现蚁群算法

    下面是关于“Python实现蚁群算法”的完整攻略。 1. 蚁群算法简介 蚁群算法是一种基于蚂蚁觅食行为的启发式优化算法。蚁群算法通过蚂蚁在寻找食物时的行为,来寻找最优解。蚁群算法适用求解组合优化问题,如旅商问题车辆路径问题等。 2. Python实现蚁群算法 在Python中,我们可以使用 numpy 和 matplotlib 等库实现蚁算法。下面是一个使用…

    python 2023年5月13日
    00
  • JavaScript树形数据结构处理

    对于“JavaScript树形数据结构处理”的完整攻略,我将从以下几个方面进行讲解: 树形数据结构的简介 树形数据结构在JavaScript中的表示 树形数据结构的处理方法 示例说明 树形数据结构的简介 树形数据结构,是一种常见的数据结构,由多个节点组成,每个节点有一个父节点和多个子节点。树形数据结构通常用来表示层级关系的数据。 树形数据结构在JavaScr…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部