zoukankan      html  css  js  c++  java
  • 【基础操作】博弈论 / SG 函数详解

      博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子)

      先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 

      This article was updated at 2019.8.14.

    SG函数

      在学习博弈论之前,你需要彻底了解 SG 函数。

      对于一个两人轮流操作的游戏,我们把游戏的每一种可能的局面设为一种局面

      那么局面只分两种:(对于这一轮操作者的)必胜态必败态至于为什么没有不确定态,看完下文你就明白了。

      若这一轮操作者从这个局面出发,按最优策略能必胜,则称这个局面为必胜态;若按最优策略也是必败,则称这个局面为必败态。

      定义两种局面之间的转换:

        1. 终止局面为必败态

        2. 对于任意的必胜态,存在至少一条路径可以转移到必败态

        3. 对于任意的必败态,只能转移到必胜态

      解释:

        对于第 1 条,这就看游戏定义了。一般都是定义不能合法操作的人输,即到达了游戏的终止局面。

        对于第 2 条,一个玩家虽然在这一轮处于必胜态,但如果他做不当操作,可能会使对手进入必胜态,所以必胜态可能存在转移到必胜态的路径。但这个人会用最优策略,所以他会使对手必败,即选择转移到必败态的路径。所以,这个玩家处于必胜态,当且仅当该局面存在至少一条转移到必败态的路径。

        对于第 3 条,一个玩家无论怎么走都会让对面赢,说明他必败了。也可以根据定义反证 必败态不可能转移到必败态。(定义:若一个玩家通过某个转移使对手进入必败态,那他当前处于必胜态)。

        概括:若一个局面的所有后继都是必胜态,则这个局面为必败态。否则至少有一个后继是必败态,这个局面为必胜态。由于终止局面是必败态,所以从终止局面可以倒推出所有局面要么是必胜态,要么是必败态。这就是为什么博弈游戏不存在不确定态(即判断不出按最优策略是赢还是输)

      好了,理解了两种局面之间的转换,可以引入 SG(Sprague-Grundy) 函数了。它的定义如下:$$f(v) = ext{mex}{f(u)space |space u∈child[v]}$$

      其中 $ ext{mex(minimal exvludant)}$ 是定义在整数集合上的操作。它的自变量是任意整数集合,函数值是不属于该集合的最小自然数。$$ ext{mex}(A) = min{kspace |space complement_N k}$$

      那么,终止局面的 SG 值显然为 $0$,并且 SG 值为 $0$ 的局面就是必败态,SG 值不为 $0$ 的局面就是必胜态。

      理解:SG 值为 $0$ 的局面,它的所有后继局面的 SG 值都不为 $0$;SG 值不为 $0$ 的局面,它存在 SG 值为 $0$ 的后继局面。这恰好满足上文所述的两种局面之间的转移。

      所以从终止局面出发,递推出游戏中所有局面的 SG 值即可得知每种局面是必胜还是必败了。

      SG 函数不局限于上述一种定义,只要一个函数满足值为 $0$ 的局面,它的所有后继局面的 SG 值都不为 $0$;值不为 $0$ 的局面,它存在 SG 值为 $0$ 的后继局面,它就可以作为 SG 函数,表示局面是必胜还是必败。

    例题 0

      有 $n$ 个石子,$ ext{A,B}$ 轮流取 $k$ 个石子,其中 $k∈S$,$S$ 是一个给定的正整数集合。问 $ ext{A}$ 先手是否有必胜策略。

    sol

      一种石子数量对应一种局面,递推出所有局面的 SG 值即可。

    例题 1

      有 $n$ 个式子,$ ext{A,B}$ 两人轮流取石子,规定他们每次至多只能取当前石子总数 $lceil frac{s}{2} ceil$ 个式子。问 $ ext{A}$ 先手是否有必胜策略。

    sol

      列出 $n$ 很小时 $ ext{SG}(n)$ 的值,发现 SG 值有规律

      0, 1

      0, 2, 1, 3

      0, 4, 2, 5, 1, 6, 3, 7

      0, 8, 4, 9, 2, 10 ……

      这就是本题的规律,先手必败当且仅当 SG 值为 $0$。

    例题 2(Nim 游戏)

      有 $n$ 堆石子,每堆数目分别为 $x_1,x_2,...,x_n$,$ ext{A,B}$ 两人每次可以选一堆石子取走任意多个,问 $ ext{A}$ 先手是否有必胜策略。

    sol

      例题 0 的扩展版本。

      由于这里有多堆石子,我们考虑对每堆石子求出 $ ext{SG}(x_i)$。然而由于这里不限制取石子的数量,所以实际上 $ ext{SG}(n) = ext{mex}{ ext{SG}(0), ext{SG}(1), ...,  ext{SG}(n-1)}$,归纳可得 $ ext{SG}(n) = n$,所以 $ ext{SG}(x_i) = x_i$。

      能否由这一些 SG 值得到整局游戏的 SG 值呢?

      Nim 游戏的神奇之处在于它的 SG 值和异或扯上了关系。Nim 游戏中先手必败当且仅当 $x_1igoplus x_2igoplus ...igoplus x_n = 0$($igoplus$ 为异或)。

      证明:

        当 Nim 游戏的 SG 值为 $0$ 时,我们假定取第 $k$ 堆中的某些石子,使得 $x_k$ 减成 $x'_k$,我们假设 $x_1igoplus x_2igoplus ...igoplus x_n = 0 = x_1igoplus x_2igoplus ...igoplus x'_kigoplus ...igoplus x_n$,可得 $x_k=x'_k$,不符合条件,因此在取一轮石子后 SG 值必然发生了改变。

        而对于一个 SG 值不为 $0$ 的局面,我们必然可以通过一个操作,使得 SG 值变为 $0$。设 SG 值为 $sum$,若其最高位为(从个位数起)第 $k$ 位,则至少存在一个 $x_i$,其第 $k$ 位是 $1$。从这堆(第 $i$ 堆)中取走若干个石子,可以使 $x_i$ 的第 $k$ 位变成 $0$,然后因为这样一定会使 $x_i$ 变小,所以我们可以自由确定第 $1$ 到 $k-1$ 位是 $0$ 还是 $1$。把 $sum$ 的每一位异或成 $0$ 即可。

      综上,所有 $x_i$ 的异或和 满足 SG 函数的转移性质,可以作为 SG 函数。

    例题 3(Nimk)

      有 $n$ 堆石子,第 $i$ 堆数目分别为 $x_i$,$ ext{A,B}$ 两人每次可以选最多 $k$ 堆石子,并从选中的每堆石子中取走任意多个,问 $ ext{A}$ 先手是否有必胜策略。

    sol

      Nimk 就是 Nim 游戏的一个简单扩展。

      先手存在必胜策略,当且仅当:将所有石子数转成二进制后,存在一个 $i$,使得所有二进制数的第 $i$ 位上 $1$ 的总数 $mod (k+1)$ 不为 $0$。

      证明:

        当 Nimk 游戏的 SG 值为 $0$ 时,由于我们每次最多只能选 $k$ 堆,所以我们不能在同一二进制位上改变 $k+1$ 个值,因此在取一轮石子后 SG 值必然发生了改变。

        而对于一个 SG 值不为 $0$ 的局面,必然存在一种取石子方式,使其转移到必败局面。

        不妨设必胜局面下,$1$ 的个数 $mod (k+1)$ 不为 $0$ 的最高二进制位上有 $m$ 个 $1$,设该二进制位为从低到高数第 $i$ 位,则将 $1$ 的个数改成 $k+1$ 的倍数 需要将该二进制位为 $1$ 的 $m$ 堆石子的数量都减 $2^(i-1)$。我们现在就取这 $m$ 堆

        然后再找 $1$ 的个数 $mod (k+1)$ 不为 $0$ 的最高二进制位,设该位上有 $n$ 个 $1$,并且记之前改变的 $m$ 堆石子在该位上有 $a$ 个 $1$ 和 $b$ 个 $0$($m,n,a,b$ 都是 $mod (k+1)$ 后的值)。

        分情况讨论:

          1. $age n$,则将之前 $m$ 堆石子中的 $n$ 个 $1→0$,这样不会改变更多堆石子

          2. $bge k+1-n$,则将之前 $m$ 堆石子中的 $k+1-n$ 个 $0→1$,这样不会改变更多堆石子

          3. $alt r$ 且 $blt k+1-r$,则将之前 $m$ 堆以外的 $m-a$ 堆的 $1→0$。那么此时改变的堆数为 $m+r-a → a+b+r-a → b+r$,又因为 $b+rlt k+1-r+r → k+1$,所以我们改变的堆数 $m+r-alt k+1$,是合法的。

        重复上述操作,我们必然能使每一位上 $1$ 的个数 $mod (k+1)$ 为 $0$,即转移到必败态。

     

      Nim 游戏相当于 Nimk 中 $k=1$ 的情况。

    练习 1(uoj 266)

      给定一棵 $n$ 个节点的森林,每个连通块的根是块内编号最小的点。每个点有黑白两种颜色中的一种。$ ext{A}$ 和 $ ext{B}$ 轮流选择一个白点,将该点到根的路径上所有点都涂黑。谁无法操作谁输。问 $ ext{A}$ 先手是否有必胜策略。

      题意等价于每次选择一个点,删除该点及其所有祖先。

    sol

      下面的所有加法 $+$ 都表示不进位加法 $ ext{xor}$。

      考虑树形 $ ext{dp}$,根据题意设后继局面。

      对于这种树形题目,肯定是将以每个点为根的子树设为一个子游戏,然后以一个点为根的子树对应的子游戏的 $ ext{SG}$ 值(下文简称为子游戏 $x$) 由这棵子树中若干个子游戏的 $ ext{SG}$ 值转移来。

      正好题目要求记第一个涂黑的数,于是我们

        设 $f(x)$ 为以 $x$ 为根的子树的 $ ext{SG}$ 值。

        设 $g(x,y)$ 为以 $x$ 为根的子树中,第一步涂黑了子树中的点 $y$ 后的 $ ext{SG}$ 值。

        设 $sum(x) = sumlimits_{y∈son(x)} f(y)$。

      不难发现, $g(x,y)$ 就是子游戏 $x$ 的一个后继局面集合

      考虑 $g$ 的转移。由于涂黑 $z$ 到子游戏 $x$ 的根节点 $x$ 路径上的所有点 相当于删掉这些点,于是剩下的每棵连通子树(即图中的所有三角)形成了一个新的子游戏。这些子游戏的 $ ext{SG}$ 值之和就是子游戏 $x$ 的 $ ext{SG}$ 值。

      终止局面:$$g(x,x)=sum(x)$$。即删掉这个点后,它的所有儿子子树形成了互不关联的子游戏,我们只需要取这些游戏的 $ ext{SG}$ 值之和即可。

      一般局面:对于 $z≠x$ 的 $g(x,z)$,画个图(粗线表示一条链,链上的若干节点就不画了;三角表示一棵子树)

      不我们需要求所有三角子树对应的子游戏的 $ ext{SG}$ 之和。

      那我们需要暴力跑一遍这条链吗?(其实暴力跑可以做到同一复杂度,但这样就没法优化做法了)

      不难发现,在 $x$ 的所有儿子中,$g(y,z)$ 已经帮我们记好了以 $y$ 为根的子树中这些三角的 $ ext{SG}$ 值之和。

      于是有 $$g(x,z) = g(y,z)+sumlimits_{y'in son(x), z otin subtree(y')} f(y') = g(y,z)+(sumlimits_{y'in son(x)} f(y'))+f(y)spacespace | spacespace zin subtree(y)$$

      有人可能要问了:这不是 Nim 游戏,为什么一个局面的 $ ext{SG}$ 值还是它后继子游戏的 $ ext{SG}$ 值的异或和?

      其实对于所有简单组合游戏,我们可以将组成它的所有子游戏换成相应数目的一堆石子,这样所有的游戏都等价于 Nim 游戏。详情参考该论文的第 $7-8$ 页.

      upd:这篇论文据说不少结论都写错了,实际上其它游戏并不等价于 Nim 游戏。关于这题的异或原因见下:

        首先你需要普及一个知识 —— SG 定理:游戏和的 SG 函数等于各个游戏 SG 函数的 Nim 和(异或和)。

        然后我们对于这道题来尝试证明 SG 定理!

        考虑 Nim 游戏,它为什么能把每堆石子的数量异或起来,作为全局的 $ ext{SG}$ 函数?关键原因是对于一堆数量为 $x$ 的石子,它可以变为 $0$ 到 $x-1$ 中的任意一个数!

        但我们仔细想想,为什么在 Nim 游戏是求每个子游戏(每堆石子)的数量的异或和,而 SG 定理是求每个子游戏的 SG 函数的异或和呢?

        之前是不是解释过,Nim 游戏中 $ ext{SG}(x)=x$?

        所以 Nim 游戏也是求每个子游戏的数量的异或和嘛!

        所以对于这类博弈游戏,求每个子游戏的数量的异或和,关键在于对于任意一个子游戏,设其 $ ext{SG}$ 值为 $ ext{SG}(x)$,它必须能转移到 $ ext{SG}$ 值为 $[0, ext{SG}(x)-1]$ 中整数的所有局面。

        那任意一个子游戏都是如此么?

        以这道题为例,一棵子树对应一个子游戏,我们考虑这个子游戏的 $ ext{SG}$ 值的含义 —— 对该子游戏分解出的所有后继局面(每个后继局面都是一个子游戏集合)的 $ ext{SG}$ 值求 $ ext{mex}$。

        既然是求 $ ext{mex}$,那不就说明这个子游戏包含 $ ext{SG}$ 值为 $0,1,2,..., ext{SG}(x)-1$ 的后代么?

        然后我们重新梳理一下一堆子游戏放在一起的概念。

        

        对于一棵树(你也可以假设其为初始局面),将一个点到根的路径删掉(图中加粗线条),就会分成很多个子游戏。分出的子游戏集合就是当前子游戏的一个后继局面。

        对于一个后继局面对应的子游戏集合 $S$,将一个子游戏 $A$ 中的一个点到根的路径删掉,$A$ 就又分成了若干个子游戏。我们用这若干个子游戏替换掉 $S$ 中的 $A$ 得到 $S'$,则 $S'$ 又是 $S$ 的后继。

        也就是说,局面一直是相对于整个游戏而言的

        而我们可以任选子树中的一个点,将它到根的路径删掉。选择的点不同,后继局面也不同,所以一个局面有很多后继局面。

        显然这个局面的 $ ext{SG}$ 值就是所有后继局面的 $ ext{SG}$ 值的 $ ext{mex}$。

        但一个后继局面可能是很多子游戏组成的集合,该局面的 $ ext{SG}$ 值就是每个子游戏的 $ ext{SG}$ 值得异或和。

        这时不难发现,局面 -> 子游戏集合,$ ext{SG}$ 值的转移只发生在不同的子游戏集合间。

        在 Nim 游戏中,子游戏集合的大小不变,相邻两个局面的子游戏集合只有一个数不同。

        在这个游戏中,子游戏集合的大小会变,但对于相邻两个局面,若前驱局面的 $ ext{SG}$ 值不为 $0$,则前驱局面1一定可以选出一个子游戏,将其拆成若干个子游戏,使这个局面的 $ ext{SG}$ 值为 $0$,而这就是前驱局面的某个后继局面;若前驱局面的 $ ext{SG}$ 值为 $0$,由于集合中每个子游戏的 $ ext{SG}$ 值都是该子游戏的所有后继局面的 $ ext{SG}$ 值的 $ ext{mex}$,所以该集合中不存在一个子游戏 $A$,使得这个子游戏存在一个后继局面 $B$,满足 $ ext{SG}(A)= ext{SG}(B)$,进而得出该前驱局面的后继局面的 $ ext{SG}$ 值一定会变为非 $0$。

        不难发现这种子游戏集合间的转移满足 $ ext{SG}$ 函数的转移要求。

        实际计算时,我们从终止局面出发, $ ext{dp}$ 出每个子游戏的 $ ext{SG}$ 值即可,因为你显然不可能记下每个局面对应的子游戏集合,而我们只需要知道一个子游戏集合中的每个子游戏的 $ ext{SG}$ 值,而一个子游戏是原树的一个子树,故只有 $n$ 个。再结合这题的 $ ext{dp}$ 方式,就只有 $n^2$ 种实际存在的局面了。

        Q.E.D

      然后考虑 $f$ 的转移,由于 $g(x,i)$ 都是子游戏 $x$ 的后继局面,所以 $f(x) = ext{mex}(g(x,i)space |space iin subtree(x))$。

      有了 $f$ 和 $g$ 的转移,暴力 $ ext{dp}$ 是 $O(n^2)$ 的。

      code

      下面考虑数据结构优化 $ ext{dp}$。

      用一棵 $ ext{01trie}$ 维护每个点 $x$ 的数组 $g_x(z)$。

      则 $g_x$ 由所有 $g_y$ 整体异或 $f(y)$ 后合并起来 再整体异或 $sumlimits_{yin son(x)} f(y)$ 得到(也可以直接对每个 $g_y$ 整体异或 $f(y) + sumlimits_{yin son(x)} f(y)$)。

      然后我们需要对 $g_x$ 求 $ ext{mex}$ 得到 $f(x)$。

      $ ext{01trie}$ 可以轻松维护整体异或一个值、求 $ ext{mex}$。对于整体异或一个值,打 $ ext{tag}$ 记录以该点为根的子树要异或的值 $x$ ,若 $x$ 在该点对应的二进制位为 $1$ 则交换该点的左右儿子;对于求 $ ext{mex}$,直接在 $ ext{trie}$ 树上二分,若左子树未满则往左走,满了则往右走。

      由于 $ ext{SG}$ 值 $le n$,故总复杂度为 $O(nlog n)$。

      code

    update:

      我在 $ ext{uoj}$ 翻 $ ext{60pts}$ 代码时,看到了一个奇怪的代码

      不难发现,他在 $ ext{dfs2}$ 中写了这么一句:if(FLAG) tot[0]+=coef;

      这显然有问题,因为 $ ext{dfs2}$ 实质上是在枚举 $g(x,z)$ 的 $z$,而上面这句没有对应的 $z$,对于叶子节点也不应该有任何特殊操作,不知道作者是怎么想的居然能写出这么明显的问题。

      他这么写,相当于默认任何状态都有一个值为 $0$ 的后继状态。当时我就跟 scb 神仙讨论了一下,他也不知道这是什么道理。于是我们在 ezoj 上翻了一下这道题的简化版 —— 保证 $n$ 个点由 $n-1$ 条边连通成一棵树,结果发现那题的数据全是 $ ext{Alice}$ 必胜

      回来看了下这道题,发现在只有一棵连通树的情况下,$ ext{SG}$ 值一定不为 $0$,即 $ ext{Alice}$ 必胜。样例中唯一一组 $ ext{Bob}$ 赢的数据还是两个不相连的单点。

      我们很疑惑,于是尝试构造了几组一棵连通树的数据,很快发现构造出的数据的 $ ext{SG}$ 值全不为 $0$……

      scb 帮忙上交友群问了一下证明·,发现很简单……

      对于一棵连通树,让 $ ext{Alice}$ 先选根节点,若去掉根节点后的局面为必败态,那 $ ext{Alice}$ 当然就赢了;

      若为必胜态,则 $ ext{Bob}$ 可以通过选择某个点让 $ ext{Alice}$ 必败,也就是让 $ ext{Bob}$ 必胜。但不难发现由于 $ ext{Alice}$ 选的点是根,所以一定是 $ ext{Bob}$ 选的点的祖先,在选择某个点之前选择它的祖先 是无用操作(因为一次操作是选择某个点,将其和所有祖先涂黑),故让 $ ext{Alice}$ 一开始不选根节点 而选这个点,$ ext{Alice}$ 就必胜了。

      这个证明思路和一个类似的游戏很像 —— $n imes m$ 的棋盘,每次去掉一个格子及其右下角所有格子。

    后记

      这玩意可能不怎么考,不要过度痴迷。

  • 相关阅读:
    数据操作-apply函数族
    11.盛水最多的容器
    canvas绘图
    Nodejs事件监听模块
    http性能测试
    源码解读
    nodejs的一些概念
    http知识补充
    querystring处理参数小利器
    url网址解析的好帮手
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/game_theory.html
Copyright © 2011-2022 走看看