博弈论 SG函数

(1) 玩家:2人;
(2) 道具:23张扑克牌;
(3) 规则:
游戏双方轮流取牌;
每人每次仅限于取1张、2张或3张牌;
扑克牌取光,则游戏结束;
最后取牌的一方为胜者。
想一下。。
首先申明一点,博弈的讨论是在大家都玩的最好的情况下讨论的。(如果2个玩家智商有差别,那就没法讨论了~~~~开个玩笑哈。)
介绍概念:P点 即必败点,某玩家位于此点,只要对方无失误,则必败;
N点 即必胜点,某玩家位于此点,只要自己无失误,则必胜。
定理:
一、 所有终结点都是必败点P(上游戏中,轮到谁拿牌,还剩0张牌的时候,此人就输了,因为无牌可取);
二、所有一步能走到必败点P的就是N点;
三、通过一步操作只能到N点的就是P点;
自己画下图看看。
x :0 1 2 3 4 5 6 7 8 9 10。。。
pos:P N N N P N N N P N N 。。。
所以若玩家甲位于N点。只要每次把P点让给对方,则甲必胜;
反之,若玩家甲位于P点,他每次只能走到N点,而只要乙每次把P点让给甲,甲必败;
这里好好理解下;
如果上面的理解的。请解决下面的题目:HDU 1846 2147(注意题目限制内存)(先2道练练手,做不出的话提示:找规律)
接下来介绍Nim游戏(同样引用杭电上的,懒的打字)
1.有两个玩家;
2. 有三堆扑克牌(比如:可以分别是 5,7,9张);
3. 游戏双方轮流操作;
4. 玩家的每次操作是选择其中某一堆牌,然后从中取走任意张;
5.最后一次取牌的一方为获胜方;
想一会:
还记得刚才说的P点和N点吗?P:必败点,N:必胜点
先给出结论,这里要用到位运算,异或:^
游戏的某个位置(x1,x2,x3) x1,x2,x3表示3堆的个数。当且仅当 x1^x2^x3=0时,此点才是必败点P;
结论可以推广到一般情况,即有n堆,(x1,x2,x3,…xn) 当且仅当x1^x2^x3…^xn=0时,此点才是必败点P;
如要看证明过程,链接在此 http://acm.hdu.edu.cn/forum/read.php?fid=9&tid=10617,看不懂的可以问 我(汗。。)
练习:HDU 2188 2149 (做不出的话先看下面的,然后多思考)
下面介绍sg函数(解决博弈问题的王道)
sg 即Graph Game,把博弈游戏抽象成有向无环图
(1) 有向无环图
(2) 玩家1先移动,起点是x0
(3) 两个玩家轮流移动
(4) 对于顶点x, 玩家能够移动到的顶点集记为F(x).
(5) 不能移动的玩家会输掉游戏
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、 mex{2,3,5}=0、mex{}=0。
定义: 一个图的Sprague-Grundy函数(X,F)是定义在X上的非负函数g(x),并且满足:
g(x) = mex{g(y) : y∈F(x)}
看到这里先好好理解一下sg值是怎么求的;
如果在取子游戏中每次只能取{1,2,3},那么各个数的SG值是多少?
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14…
g(x) 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2…
看看这个和上面那个图的规律:
P-点: 即令 g(x) = 0 的 x 点!
N-点: 即令 g(x) > 0 的 x 点!
练习 HDU 1847 1849 1850 (做不出的话先看下面的,然后多思考)
最后看下组合博弈,就是把简单的游戏组合起来,比如3堆的可以看成3个一堆的游戏。
定理:
假设游戏 Gi的SG函数是gi, i=1,…,n, 则
G = G1 + … + Gn 的 SG函数是
g(x1,…,xn) = g1(x1)⊕…⊕gn(xn).
其中那个符合就是异或^。

SG函数模板

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

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

例如:取石子问题,有1堆n个的石子,每次只能取{1,3,4}个石子,先取完石子者胜利,那么各个数的SG值为多少?

sg[0]=0,f[]={1,3,4},

x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;

x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;

x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;

x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;

x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;

以此类推…..

x 0 1 2 3 4 5 6 7 8….

sg[x] 0 1 0 1 2 3 2 0 1….

计算从1-n范围内的SG值。

f(存储可以走的步数,f[0]表示可以有多少种走法)

f[]需要从小到大排序

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

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

3.可选步数为一系列不连续的数,用GetSG()计算

模板1如下(SG打表):

//f[]:可以取走的石子个数 
//sg[]:0~n的SG函数值 
//hash[]:mex{} 
 int f[N];//可以取走的石子个数 
int sg[N];//0~n的SG函数值 
int Hash[N];

void getSG(int n){ 
 memset(sg,0,sizeof(sg)); 
 for(int i = 1; i <= n; i++){ 
 memset(Hash,0,sizeof(Hash)); 
 for(int j = 1; f[j] <= i; j++) 
 Hash[sg[i-f[j]]] = 1; 
 for(int j = 0; j <= n; j++){ //求mes{}中未出现的最小的非负整数 
if(Hash[j] == 0){ 
 sg[i] = j; 
 break; 
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值