(转)博弈 SG函数

此文为以下博客做的摘要:

https://blog.csdn.net/strangedbly/article/details/51137432

----------------------------------------------------------------------------------------

1、定义P-position和N-positon

P表示Previous,N表示Next。

即上一个移动的人有必胜策略的局面是P-position,“先手必败”或“后手必胜”,现在移动的人有必胜策略的局面是N-positon,“后手必败”或“先手必胜”。下面为更严谨的定义:

1、无法进行任何移动的局面(即terminal position)是P-position;

2、可以移动到P-position的局面是N-position;

3、所有移动都导致N-position的局面是P-position。

根据定义,不重现局面,那么positions的集合可以进行拓扑排序,并且能通过定义判断为P-position还是N-position。

2、Nim游戏及Bouton‘s Theorem

Bouton‘s Theorem :对于一个Nim游戏的局面(a1, a2, ...an),它是P-position当且仅当 a1^a2^...^an = 0,其中 ^ 表示异或运算。

要证明这个定理,基本上是证明这种运算符合上述position的定义。即证明三个命题:1、这个判断将所有无法移动的局面判为P-position;2、被判为N-position的局面一定可以移动到某个P-position;3、被判为P-position的局面无法移动到某个P-position。

第一个命题:无法移动的局面只有全为0,即异或仍为0。

第二个命题:对于某个局面(a1,a2,...,an),若a1^a2^...^an!=0,一定存在某个合法的移动,将ai改变成ai‘后满足a1^a2^...^ai‘^...^an=0。不妨设a1^a2^...^an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的最高位那个1是怎么得到的)。这时ai^k<ai一定成立。则我们可以将ai改变成ai‘=ai^k,此时a1^a2^...^ai‘^...^an=a1^a2^...^an^k=0。

第三个命题:对于某个局面(a1,a2,...,an),若a1^a2^...^an=0,一定不存在某个合法的移动,将ai改变成ai‘后满足a1^a2^...^ai‘^...^an=0。因为异或运算满足消去率,由a1^a2^...^an=a1^a2^...^ai‘^...^an可以得到ai=ai‘。所以将ai改变成ai‘不是一个合法的移动。证毕。

3、Sprague-Grundy函数

首先给出这个函数适用范围,貌似所有博弈的题目都是符合这个范围。现在来研究似乎更为一般的游戏:给定一个有向无环图和一个其实顶点上的一枚棋子,两名选手交替将这棋子沿有向边移动,无法移动者判负。事实上,这个游戏可以认为是所有Impartial Combinatorial Games的抽象模型。即任何一个ICG都可以通过把每个局面看成一个顶点,对每个局面和它的子局面连一条有向边来抽象成这个“有向图游戏”。

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:g(x)=mex{ g(y) | y是x的后继 }。

来看一下SG函数的性质。首先,所有的terminal position所对应的顶点,也就是没有出边的顶点,其SG值为0,因为它的后继集合是空集。下面为原作图

(pic1)

对于一个g(x) = 0的顶点x,它的所有后继 y 都满足 g(y) != 0。

对于一个g(x) != 0的顶点,必定存在一个后继 y 满足 g(y) = 0。

即顶点 x 代表的position为P-position,当且仅当 g(x) = 0。相应地N-position为 g(x) != 0。所以有向无环图的每个顶点SG值能够计算出来,就能找到每种局面的必胜策略。但SG函数的用途远没有这么简单。如果将有向图游戏变复杂,比如,有向图上不止有一枚棋子,而是有n枚,每次可以人选一颗移动,这时怎么找必胜策略?

考虑一下顶点的SG值的意义。当g(x) = k时,表明对于任意一个 0 <= i < k,都存在x的一个后继 y 满足g(y) = i。即当某棋子的SG值为k时,我们可以把它变成0、变成1、……、变成k-1,但绝对不能保持k不变。这类似于Nim游戏,Nim游戏的规则就是:每次选择一堆数量为k的石子,可以把它变成0、变成1、……、变成k-1,但绝对不能保持k不变。这表明,如果将n枚棋子所在的顶点的SG值看作n堆相应数量的石子,那么这个Nim游戏的每个必胜策略都对应于原来这n枚棋子的必胜策略!

对于n个棋子,设它们对应的顶点的SG值分别为(a1,a2,...,an),再设局面(a1,a2,...,an)时的Nim游戏的一种必胜策略是把ai变成k,那么原游戏的一种必胜策略就是把第i枚棋子移动到一个SG值为k的顶点。其实我们还是只要证明这种多棋子的有向图游戏的局面是P-position当且仅当所有棋子所在的位置的SG函数的异或为0。这个证明与上面的Bouton‘s Theorem几乎是完全相同的,只需要适当的改几个名词就行了。

刚才,为了使问题看上去更容易一些,认为n枚棋子是在一个有向图上移动。但如果不是在一个有向图上,而是每个棋子在其对应的有向图上,每次可以任选一个棋子(也就是任选一个有向图)进行移动,这样也不会给结论带来任何变化。

所以我们可以定义有向图游戏的和(Sum of Graph Games):设G1、G2、……、Gn是n个有向图游戏,定义游戏G是G1、G2、……、Gn的和(Sum),游戏G的移动规则是:任选一个子游戏Gi并移动上面的棋子。Sprague-Grundy Theorem就是:g(G)=g(G1)^g(G2)^...^g(Gn)。也就是说,游戏的和的SG函数值是它的所有子游戏的SG函数值的异或。

任何一个ICG都可以抽象成一个有向图游戏。所以“SG函数”和“游戏的和”的概念就不是局限于有向图游戏。我们给每个ICG的每个position定义SG值,也可以定义n个ICG的和。所以说当我们面对由n个游戏组合成的一个游戏时,只需对于每个游戏找出求它的每个局面的SG值的方法,就可以把这些SG值全部看成Nim的石子堆,然后依照找Nim的必胜策略的方法来找这个游戏的必胜策略了!(Nim其实就是n个从一堆中拿石子的游戏求SG的变型,总SG=n个sg的异或)。(very important)

有n堆石子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗……我们可以把它看作3个子游戏,第1个子游戏只有一堆石子,每次可以取1、2、3颗,很容易(看下图pic2)看出x%4==0时处于P局面,即x颗石子的局面的SG值是x%4,(即把pic2中的值改成原值%4)。第2个子游戏也是只有一堆石子,每次可以取奇数颗,经过简单的画图可以知道这个游戏有x颗石子时的SG值是x%2。第3个游戏有n-2堆石子,就是一个Nim游戏。对于原游戏的每个局面,把三个子游戏的SG值异或一下就得到了整个游戏的SG值,然后就可以根据这个SG值判断是否有必胜策略以及做出决策了。其实看作3个子游戏还是保守了些,干脆看作n个子游戏,其中第1、2个子游戏如上所述,第3个及以后的子游戏都是“1堆石子,每次取几颗都可以”,称为“任取石子游戏”,这个超简单的游戏有x颗石子的SG值显然就是x。其实,n堆石子的Nim游戏本身不就是n个“任取石子游戏”的和吗?

(pic2)

所以,对于我们来说,SG函数与“游戏的和”的概念不是让我们去组合、制造稀奇古怪的游戏,而是把遇到的看上去有些复杂的游戏试图分成若干个子游戏,对于每个比原游戏简化很多的子游戏找出它的SG函数,然后全部异或起来就得到了原游戏的SG函数,就可以解决原游戏了。

以下是本文最重要的部分:

解题模型:

1.把原游戏分解成多个独立的子游戏,则原游戏的SG函数值是它的所有子游戏的SG函数值的异或。

       sg(G)=sg(G1)^sg(G2)^...^sg(Gn)。

2.分别考虑没一个子游戏,计算其SG值。

SG值的计算方法:(重点

1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);

2.可选步数为任意步,SG(x) = x;

3.可选步数为一系列不连续的数,用模板计算。

  模板1:打表

 1 //f[], 可以取走的石头个数
 2 //sg[],SG函数值
 3 //mex[],mex{}
 4 int f[MAXN], sg[MAXN], mex[MAXN];
 5 void getSG(int n)
 6 {
 7     int i, j;
 8     memset(sg, 0, sizeof(sg));
 9     for(i = 1;i <= n;++i)
10     {
11         memset(mex, 0, sizeof(mex));
12         for(j = 1;f[j] <= i;++j)
13             mex[sg[i - f[j]] = 1;
14         for(j = 0;j <= n;++j)
15             if(mex[j] == 0)
16             {
17                 sg[i] = j;
18                 break;
19             }
20     }
21 }

  模板2:DFS

//s[i] 数组要从小排到大,SG函数要初始化为 -1, 每个集合只需初始化一遍
//n是集合s 的大小,s[i]是定义的特殊取法规则的数组
int s[105], sg[10005], n;
//memset(sg, -1, sizeof(sg));
//sort(s, s + n);
int SG_dfs(int x)
{
    int i;
    if(sg[x] != -1)
        return sg[x];
    bool vis[105];
    memset(vis, 0, sizeof(vis));
    for(i = 0;i < n;++i)
    {
        if(x >= s[i])
        {
            SG_dfs(x - s[i]);
            vis[sg[x - s[i]] = 1;//mex{}
        }
    }
    int e;
    for(i = 0;;++i)
        if(!vis[i])
        {
            e = i;
            break;
        }
    return sg[x] = e;
}

首选打表,实在不行才用DFS。

--------------------------------------------------------------------------------------------

原博主下面还有题,另外也开了一篇写题的博客

原文地址:https://www.cnblogs.com/shuizhidao/p/9271712.html

时间: 2024-10-09 10:38:44

(转)博弈 SG函数的相关文章

UVA 10561 - Treblecross(博弈SG函数)

UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',可以在'.'的位置放X,谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败),所以可以以X分为几个子游戏去求SG函数的异或和进行判断,至于求策略,就是枚举每个位置就可以了 代码: #include <stdio.h> #include <string.h> #include <algorithm> usi

hdu 3032(博弈sg函数)

题意:与原来基本的尼姆博弈不同的是,可以将一堆石子分成两堆石子也算一步操作,其它的都是一样的. 分析:由于石子的堆数和每一堆石子的数量都很大,所以肯定不能用搜索去求sg函数,现在我们只能通过找规律的办法求得sg的规律. 通过打表找规律可以得到如下规律:if(x%4==0) sg[x]=x-1; if(x%4==1||x%4==2) sg[x]=x; if(x%4==3) sg[x] = x+1. 打表代码: #include<iostream> #include<cstdio> #

UVA 11534 - Say Goodbye to Tic-Tac-Toe(博弈sg函数)

UVA 11534 - Say Goodbye to Tic-Tac-Toe 题目链接 题意:给定一个序列,轮流放XO,要求不能有连续的XX或OO,最后一个放的人赢,问谁赢 思路:sg函数,每一段...看成一个子游戏,利用记忆化求sg值,记忆化的状态要记录下左边和右边是X还是O即可 代码: #include <stdio.h> #include <string.h> const int N = 105; int t, sg[3][3][N]; char str[N]; int ge

HDOJ 5724 博弈SG函数

链接: http://blog.csdn.net/tc_to_top/article/details/51958964 题意: n行20列的棋盘,对于每行,如果当前棋子右边没棋子,那可以直接放到右边,如果有就跳过放到其后面的第一个空位子,A先操作,最后谁无法操作则输,给定每行棋子状态,问先手是否必胜 题解: 组合博弈问题,直接sg函数,因为列只有20,可以状压搞,枚举每个状态,找到该状态下可行的操作然后标记 代码: 31 int sg[1 << 21]; 32 int vis[21]; 33

Marbles(博弈SG函数)

Marbles Gym - 101908B Using marbles as a currency didn't go so well in Cubic?nia. In an attempt to make it up to his friends after stealing their marbles, the Emperor decided to invite them to a game night in his palace. Of course, the game uses marb

[hdu-5795]A Simple Nim 博弈 尼姆博弈 SG函数打表找规律

[题目]题目链接 Two players take turns picking candies from n heaps,the player who picks the last one will win the game.On each turn they can pick any number of candies which come from the same heap(picking no candy is not allowed).To make the game more int

Light OJ 1296 - Again Stone Game (博弈sg函数递推)

F - Again Stone Game Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Alice and Bob are playing a stone game. Initially there are n piles of stones and each pile contains some stone. Alice stars the

Light OJ 1199 - Partitioning Game (博弈sg函数)

D - Partitioning Game Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Alice and Bob are playing a strange game. The rules of the game are: Initially there are n piles. A pile is formed by some cell

LightOJ 1315 - Game of Hyper Knights(博弈sg函数)

G - Game of Hyper Knights Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description A Hyper Knight is like a chess knight except it has some special moves that a regular knight cannot do. Alice and Bob are p