SG函数入门
必胜点与必败点
概念
P点:必败点,换句话说,就是在双方都选择最优策略的情况下,谁处于此状态谁必败。
N点:必胜点,换句话说,就是在双方都选择最优策略的情况下,谁处于此状态谁必胜。
性质
1.所有的终结点都是必败点P。
2.从任意的必胜点N进行操作,至少有一种方式到达一个必败点。
3.从任意的一个必败点P进行操作,只可能到达必胜点N。
我们研究必胜点与必败点的目的是以此为题来简化博弈的情况,有助于我们分析策略。通常我们分析必胜点和必败点都是以终结点为起始点进行逆序分析。
我们以一道题为例
例题
题目描述
大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此。当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考前的放松,所谓“张弛有道”就是这个意思。这不,Kiki和Cici在每天晚上休息之前都要玩一会儿扑克牌以放松神经。
“升级”?“双扣”?“红五”?还是“斗地主”? 当然都不是!那多俗啊~ 作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的: 1、 总共n张牌; 2、 双方轮流抓牌; 3、 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…) 4、 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者; 假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢? 当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。题目大意
现在有n张牌两个人取每次每个人只能取\(2^k\)张牌问是否先手必胜(肯定有万恶的多组数据)
当 n = 0 时,显然为必败点,因为此时你已经无法进行操作了
当 n = 1 时,因为你一次就可以拿完所有牌,故此时为必胜点
当 n = 2 时,也是一次就可以拿完,故此时为必胜点
当 n = 3 时,要么就是剩一张要么剩两张,无论怎么取对方都将面对必胜点,故这一点为必败点。
以此类推,最后你就可以得到;
n : 0 1 2 3 4 5 6 ...
position: P N N P N N P ...
然后我们发现这道题的 P/N点的分布是有规律的,所以我们就可以O(T)的求解这道题了。
然后呢我们来考虑更加复杂的一个问题
例题
题意
先说题意,有两个人在玩一个方格游戏,起初是一个n×m的方格,刚开始在(1,m)坐标处有一个石子,每一次每个人可以把石子移向向下,向左,向左下,等到当前的人无法进行移动时,这个人失败,每次都是先手先走,问最终的答案。
思路
这是一道非常裸的NP状态转移的博弈问题。
这类题我们最好画一个表格,然后发挥自己的想象去找规律。
由于我们每次只能向左下角走,所以显然左下角为必败点。
那么所有可以到达这个点的点都为必胜点,然后我们一步步往下推最后一定可以得到一个类似这样的表格。
P | N | P | N |
---|---|---|---|
N | N | N | N |
P | N | P | N |
N | N | N | N |
P | N | P | N |
我们可以发现规律只有当行列都为奇数时才为必败点,其他情况均为必胜点
所以这道题当行列都为奇数时Kiki无法赢得比赛。
SG 函数
首先我们需要先了解一个运算mex,这是一个对于集合的运算,mex(S)表示集合S中最小没有出现过的自然数。例如:mex{0,1,2,4}=3,mex{2,3,5}=0,mex{}=0
对于任意状态x,我们定义SG(X)=mex(S),其中S表示x的后继状态的SG函数值的集合。举个栗子:x有三个后继状态分别为SG(a),SG(b),SG(c);那么SG(x)=mex{SG(a),SG(b),SG(c)}。这样的集合S的最终状态必然是空集,所以当某一点的SG(x)=0,当且仅当x为为必败点时成立。
Sprague-Grundy定理(SG定理)
游戏的SG和等于各个游戏的SG函数的Nim和。这样就可以把一个游戏分而治之,从而简化问题。而Bouton定理就是SG定理在Nin游戏中的直接应用,因为单堆的Nim游戏SG函数满足SG(x)=x.
举个栗子
取石子
题面
有1堆n个的石子,每次只能取{ 1, 3, 4 }个石子,先取完石子者胜利,那么各个数的SG值为多少?
思路
先找终结点当个数为0时。那么有SG[0]=0,f[]={1,3,4}.
x=1时,可以取走1-f[1]个石子,剩余{0}个,所以SG[1]=mex{SG[0]}=mex{0}=1;
x=2时,可以取走2-f[1]个石子,剩余{1}个,所以SG[2]=mex{SG[1]}=mex{1}=0;
x=3时,可以取走3 - f{1,3}个石子,剩余{2,0}个,所以 SG[3] = mex{SG[2],SG[0]} = mex{0,0} =1;
x=4 时,可以取走4- f{1,3,4}个石子,剩余{3,1,0}个,所以SG[4]=mex{SG[3],SG[1],SG[0]} = mex{1,1,0} = 2;
x=5 时,可以取走5 - f{1,3,4}个石子,剩余{4,2,1}个,所以SG[5]=mex{SG[4],SG[2],SG[1]} =mex{2,0,1} = 3;
以此类推……
x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
SG[X] | 0 | 1 | 0 | 1 | 2 | 3 | 2 | 0 |
由上述实例我们就可以得到SG函数值求解步骤,那么计算1~n的SG函数值步骤如下:
1、使用 数组f 将 可改变当前状态 的方式记录下来。
2、然后我们使用 另一个数组 将当前状态x 的后继状态标记。
3、最后模拟mex运算,也就是我们在标记值中 搜索 未被标记值 的最小值,将其赋值给SG(x)。
4、我们不断的重复 2 - 3 的步骤,就完成了 计算1~n 的函数值。
//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; } }}
题面
任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:
F(1)=1; F(2)=2; F(n)=F(n-1)+F(n-2)(n>=3); 所以,1,2,3,5,8,13……就是菲波那契数列。 在HDOJ上有不少相关的题目,比如1005 Fibonacci again就是曾经的浙江省赛题。 今天,又一个关于Fibonacci的题目出现了,它是一个小游戏,定义如下: 1、 这是一个二人游戏; 2、 一共有3堆石子,数量分别是m, n, p个; 3、 两人轮流走; 4、 每走一步可以选择任意一堆石子,然后取走f个; 5、 f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量); 6、 最先取光所有石子的人为胜者;假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
数据范围为1000
#include#include #define MAXN 1000 + 10#define N 20int f[N],SG[MAXN],S[MAXN];void getSG(int n){ int i,j; memset(SG,0,sizeof(SG)); 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; for(j = 0;;j++) if(!S[j]){ SG[i] = j; break; } }}int main(){ int n,m,k; f[0] = f[1] = 1; for(int i = 2; i <= 16; i++) f[i] = f[i-1] + f[i-2]; getSG(1000); while(scanf("%d%d%d",&m,&n,&k),m||n||k){ if(SG[n]^SG[m]^SG[k]) printf("Fibo\n"); else printf("Nacci\n"); } return 0;}
其他题目
POJ 2234 Matches Game
HOJ 4388 Stone Game IIPOJ 2975 Nim
HOJ 1367 A Stone Game POJ 2505 A multiplication game ZJU 3057 beans game POJ 1067 取石子游戏 POJ 2484 A Funny Game POJ 2425 A Chess Game POJ 2960 S-Nim POJ 1704 Georgia and Bob POJ 1740 A New Stone Game POJ 2068 Nim POJ 3480 John POJ 2348 Euclid's Game HOJ 2645 WNim POJ 3710 Christmas Game POJ 3533 Light Switching Game