SG函数入门
SG函数入门
必胜点与必败点
概念
P点:必败点,换句话说,就是在双方都选择最优策略的情况下,谁处于此状态谁必败。
N点:必胜点,换句话说,就是在双方都选择最优策略的情况下,谁处于此状态谁必胜。
性质
1.所有的终结点都是必败点P。
2.从任意的必胜点N进行操作,至少有一种方式到达一个必败点。
3.从任意的一个必败点P进行操作,只可能到达必胜点N。
我们研究必胜点与必败点的目的是以此为题来简化博弈的情况,有助于我们分析策略。通常我们分析必胜点和必败点都是以终结点为起始点进行逆序分析。
我们以一道题为例hdu 1847 Good Luck in CET-4 Everybody!
例题hdu 1847 Good Luck in CET-4 Everybody!
题目描述
大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的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)的求解这道题了。
然后呢我们来考虑更加复杂的一个问题hdu 2147 kiki's game
例题hdu 2147 kiki's game
题意
先说题意,有两个人在玩一个方格游戏,起初是一个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 again and again
题面
任何一个大学生对菲波那契数列(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 <stdio.h>
#include <string.h>
#define MAXN 1000 + 10
#define N 20
int 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 II
POJ 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