三种简单博弈&SG模板

一、巴什博弈

巴什博弈是最简单的组合游戏,大概是这样的:

只有一堆n个物品,两人轮流从这堆物品中取物,现在规定每次至少取1个,最多取m个,

最后取完的人胜.这道题我们可以使用P/N分析找到必胜点和必败点.分析如下:

我们假设最多能取3个:

我们可以很容易看出n%(m+1)=0的点都是必败态.因为在必败点上无论你怎么取,

它的后继状态都是N.

变形:如果我们规定最后取完的人输,结果又会如何.

二、威佐夫博弈

问题描述:首先有两堆石子,博弈双方每次取一堆石子中的任意个,不能不取,

或者取两堆石子中的相同个,先取完者胜利.P/N分析:

这样我们就可以找到必败状态,我们假设(a[],b[]),double k=(sqrt(5)+1)/2

(0,0)              

(1,2)        j=b-a=1          a=j*k

(3,5)        j=b-a=2          a=j*k

(4,7)        j=b-a=3          a=j*k

(6,10)      j=b-a=4          a=j*k

(8,13)      j=b-a=5          a=j*k

这里来说一个结论(证明过程略)

a[n]=((5^{1/2}+1)/2)*n

以上说明:a=(b-a)*k是一个必败态

三、Nim博弈

问题描述:有若干对石子,每堆石子的数量都是有限的,合法的移动式"选择一堆石子并拿走

若干颗(不能不拿)",如果轮到某个人时所有的石子堆都已经被拿空了,那么他就输了.

我们假设有三堆石子,分析如下:

1.(0,0,0) 显然是必败态

2.(0,n,n) 必败态 为什么? 不论我们从任意一堆中取走多少,对手都能在另外一堆中取走同样多的石子,

直到取到(0,0,0)

3.(1,2,3) 必败态 不论我们怎么取,对手都可以把局势变成(0,n,n)的情况

现在有一个定理,状态(x1,x2,x3)为必败态当且仅当x1^x2^x3=0.这里的^是二进制的逐位异或操作,

也称Nim和.假设有一个状态Nim不为0,那么这个状态一定可以通过一种取法使状态到达x1^x2^x3=0.

四、SG函数

对于任意x,定义SG(x)=mex(S),其中S是x的后继状态的SG函数值的集合,mex(S)表示不在S内的最

小的非负整数.终态(0,0,0)没有后继状态,SG=0;如果一个状态的后继状态中SG为0,那么他一定是

必胜态,否则一定是必败态.

SG代表的值是当前状态下达不到的后继状态的值.

SG函数模板:

//f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理
//SG[]:0~n的SG函数值
//S[]:为x后继状态的集合
int f[N],SG[MAXN],S[MAXN];
void  getSG(int n){
    int i,j;
    memset(SG,0,sizeof(SG));
    //因为SG[0]始终等于0,所以i从1开始
    for(i = 1; i <= n; i++){
        //每一次都要将上一状态 的 后继集合 重置
        memset(S,0,sizeof(S));
        for(j = 0; f[j] <= i && j <= N; j++)
            S[SG[i-f[j]]] = 1;  //将后继状态的SG函数值进行标记
        for(j = 0;; j++) if(!S[j]){   //查询当前后继状态SG值中最小的非零值
            SG[i] = j;
            break;
        }
    }
}

 

 

 

 

 

转载于:https://www.cnblogs.com/zut-syp/p/10543709.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值