Sprague-Grundy()函数与简单博弈论

简单博弈论


公平组合游戏 ICG


若一个游戏满足:
  • 由两名玩家交替行动;

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

  • 3.不能行动的玩家判负;
    则称该游戏为一个公平组合游戏。

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

NIM尼莫游戏


​ 给定N堆物品,第i堆物品有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜

​ 我们把这种游戏称为NIM博弈。把游戏过程中面临的状态称为局面。整局游戏第一个行动的称为先手, 第二个行动的称为后手。若在某一局面下无论采取何种行动,都会输掉游戏,则称该状态为必败态。如果当前状态可以转化为必败态,则为必胜态。

​ 所谓采取最优策略是指,若在某-局面下存在某种行动,使得行动后对面面临必败局面,则优先采取该行动。同时,这样的局面被称为必胜。我们讨论的博弈问题一般都只考虑理想情况,即NIM博弈不存在平局,只有先手必胜和先手必败两种情况。

定理: NIM博弈先手必胜,当且仅当
A 1 ⊕ A 2 ⊕ . . ⊕ A n ! = 0        ( ⊕ 为 异 或 ) A_{1} \oplus A_{2} \oplus .. \oplus A_{n} != 0\ \ \ \ \ \ (\oplus为异或) A1A2..An!=0      ()


有向图游戏

  • 给定一个有向无环图,图中有一个唯一 的起点, 在起点上放有一枚棋子。 两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负。该游戏成为有向图游戏。
  • 任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并诅从每个局面向沿着合法行动能够到达的下一个局面连有向边。

Mex运算

设S表示一个领整数集合。
定义mex(S)为求出不属于集合S的最小负整数的运算,即:
m e x ( S ) = m i n ( x )      x ∈ N   且   x ∉ S mex(S)=min(x) \ \ \ \ x\in N \ 且 \ x \notin S mex(S)=min(x)    xN  x/S
mex运算与SG函数的对应关系是:
S G ( A ) = m e x { S G ( B ) ∣ A → B } SG(A)=mex\{ SG(B)|A\rightarrow B \} SG(A)=mex{SG(B)AB}
简单来说:一个状态的SG数等于它的次态取不到的最小的SG数*

SG函数

在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1, y2, … yk,定义SG()为x的后继节点y1, y2, … yk的SG函数值构成的集合:
S G ( x ) = m e x (   { S G ( y 1 ) , S G ( y 2 ) . . . S G ( y k ) }   ) SG(x)=mex(\ \{SG(y_{1}),SG(y_{2})...SG(y_{k})\}\ ) SG(x)=mex( {SG(y1),SG(y2)...SG(yk)} )

操作方法:
  • 终点状态设置为0
  • 每个点的未知是有向图中所能走到的数中不存在的最小的非负数
  • 如果起点非0,必胜;如果起点为0,必败;
多张有向图游戏的和

​ 设G1, G2, … Gm是m个有向图游戏。定义有向图游戏G,它的行动规则是任选某个有向图游戏Gi,并在Gi上行动一步。G被称为有向图游戏G1, G2, … Gm的

​ 有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数值的异或和,即:
S G ( G ) = S G ( G 1 ) ⊕ S G ( G 2 ) ⊕ . . . ⊕ S G ( G m ) SG(G)=SG(G_{1}) \oplus SG(G_{2}) \oplus ...\oplus SG(G_{m}) SG(G)=SG(G1)SG(G2)...SG(Gm)

操作方法:

对于一个由多张有向图构成的游戏,我们在判断胜负的时候只需要判断每一张图的起点
S G ( G ′ ′ ) = S G ( x 1 ) ⊕ S G ( x 2 ) ⊕ . . . ⊕ S G ( x m )    ? =   0 SG(G^{''})=SG(x_{1}) \oplus SG(x_{2}) \oplus ...\oplus SG(x_{m})\ \ ?=\ 0 SG(G)=SG(x1)SG(x2)...SG(xm)  ?= 0
如果最终异或和为0,说明必败;否则,必胜。

SG函数模板
int SG(int x){
    if(sg[x]!=-1) return sg[x]; //如果之前已经记录此数的SG函数,直接返回
    unordered_set<int> ds;  //用哈希表记录出现过的每一个数
    
    for(int i=1;i<=k;i++)    //枚举有向图的每一个分支
        if(num[i]<=x) ds.insert(SG(x-num[i]));
    
    for(int i=0;;i++)   //检查每一个数是否出现过
        if(!ds.count(i))
            return sg[x]=i;  //最后返回的时候记录一下,即记忆化减少时间复杂度
}

练习:HDU1846,1850,1848,1527

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值