SG函数略解
由于笔者太懒,懒得把原来的markdown改成MCE,所以有很多奇怪的地方请谅解。
先说nim游戏。
大意:有n堆石子,两个人轮流取,每个人每次从任意一堆取任意个,直到一个人无法取了为止。问对于石子的情况先手的输赢。
这看上去无从入手,但是仔细想想还是有法的。
我们从最终态逆推,首先考虑(0,0,0)的情况,一看就gg了,无论谁面对这种情况都只能愿赌服输。
那么我们考虑如果我们是后手,应该怎么样才可以赢。于是我们考虑,如果出现这么一种情况(0,n,n),我们是不是处于必胜的状态。考虑当下情况,无论对方从任何一堆里取多少个,那么我们总可以从另一堆里取到相同个数然后保持当前局势。这样对方取完任何一堆,我们都可以相应的取完另一堆然后把(0,0,0)的gg局势扔给对方。
那么我们怎样才能使当前局势成为(0,n,n)呢?
我们首先从简单的例子开始:
对于情况(1,2,3),我们将这三个数二进制掉。
则:
1:01
2:10
3:11
所以1^2^3==0。
然后我们可以得出,对于任意一个f[1]^f[2]^……^f[n]==0,我们总能神乎其技的把当前情况简化成(0,n,n)来使自己必胜,反之我们就必败了。
所以我们就得出了nim游戏的一般结论。
## 然后说说sg值
先说说必败点和必胜点吧。
必败点:无论哪一方取时处于这个位置,那么必败无疑。
必胜点:无论哪一方取时处于这个位置,那么不用往后算,他已经赢了。
我们把必败点和必胜点用P和N表示。
### 给出几条性质:
1.对于任何一个必败点, 它仅能转移到必胜点。
2.对于任何一个必胜点,它都有至少一种方法转移到必败点。
3.必败点为游戏的终结点(推理基础,建立在没有平局的基础上)。
(我们以先手为第一人称)
解释一下这几个性质。
对于性质1,我们如果想要失败的话,在我们当前的位置,我们只能转移到一个必胜的位置来让对方继续。
对于性质2,我们如果要胜利,在我们当前位置,一定可以转移到一个必败点来让对方失败。
对于性质3,无论谁取到必败点,都会陷入以上两个性质的恶性循环而失去所有胜利的机会。
那么我们看一个例子:
给定一堆n个石子,两个人轮流从里面取2的幂次方个,求先手的策略。
对题目进行分析,我们可以取得个数有1,2,4,8,16,32……
那么由最终态分析:
当n=0时,为一个必败点P,因为很明显你不能操作了。
n=1时,为必胜点。
n=2时,为必胜点。
n=3时,无论怎么取,要么剩1个要么剩两个,根据性质1,我们gg了。
以此类推
n=0~7
胜负为:PNNPNNPN
规律还是比较明显的。
## 然后我们引入sg值
笔者太懒,百科复制定义了,其实也没大用:
```
游戏和的SG函数等于各个游戏SG函数的Nim和。
这样就可以将每一个子游戏分而治之,从而简化了问题。
而Bouton定理就是Sprague-Grundy定理在Nim游戏中的直接应用,因为单堆的Nim游戏SG函数满足 SG(x) = x。
```
首先我们要知道这样的一个定义:mex({?})就是集合中没出现的最小的非负整数。例如mex(1,2,3)=0,mex(0,1,2,4……)=3。
对于任意状态 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函数的终态为 SG(x) = 0,当且仅当 x 为必败点P时。
可能不好理解,还是给个例子:
假设我们有一堆n个石子,我们只能从里面取1,2,5这些。
```
那么首先:
SG[0]=0,因为总是这样的。
SG[1]=mex(0)=1
SG[2]=mex(0,1)=2
SG[3]=mex(1,2)=0
SG[4]=mex(2,3)=0
SG[5]=mex(0,3,4)=1
以此类推……
```
由此我们可以得出SG值的求法,一个状态数组f,一个后继状态集合S,加上SG即可求出。
可以做一下[Fabonacci again and again](http://acm.hdu.edu.cn/showproblem.php?pid=1848)来熟悉一下代码。
SG函数略解的更多相关文章
- 算法笔记--sg函数详解及其模板
算法笔记 参考资料:https://wenku.baidu.com/view/25540742a8956bec0975e3a8.html sg函数大神详解:http://blog.csdn.net/l ...
- 【基础操作】博弈论 / SG 函数详解
博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子) 先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 This article was updat ...
- iOS中的round/ceil/floorf函数略解
extern float ceilf(float); extern double ceil(double); extern long double ceill(long double); extern ...
- 最浅谈的SG函数
[更新] Nim游戏的经验: 每次最多取m个——%(m+1) 阶梯nim——奇数位无视,看偶数位互相独立,成一堆一堆的石子 . . . . 既然被征召去汇总算法..那么挑个简单点的SG函数好了.. 介 ...
- 博弈论基础之sg函数与nim
在算法竞赛中,博弈论题目往往是以icg.通俗的说就是两人交替操作,每步都各自合法,合法性与选手无关,只与游戏有关.往往我们需要求解在某一个游戏或几个游戏中的某个状态下,先手或后手谁会胜利的问题.就比如 ...
- (转载)--SG函数和SG定理【详解】
在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点 ...
- 博弈论 | 详解搞定组合博弈问题的SG函数
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天这篇是算法与数据结构专题的第27篇文章,我们继续深入博弈论问题.今天我们要介绍博弈论当中非常重要的一个定理和函数,通过它我们可以解决许多 ...
- hdu 1848 Fibonacci again and again (初写SG函数,详解)
思路: SG函数的应用,可取的值为不连续的固定值,可用GetSG求出SG,然后三堆数异或. SG函数相关注释见代码: 相关详细说明请结合前一篇博客: #include<stdio.h> # ...
- SG函数和SG定理【详解】
在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点 ...
随机推荐
- 性能百万/s:腾讯轻量级全局流控方案详解【转自Wetest】
阿里用的方案是在nginx中配置限流(限流功能模块是自己开发的),流量统计线上是有监控打通的,具体的限流值是通过线上流量表现+线下性能测试(模拟线上场景)测试得出的. 全新的全局流控实现方案,既解决了 ...
- android Service 保持不被杀死
Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,然后在onStart ...
- 二、Android应用的界面编程(二)布局管理器
一.线性布局所有布局都可以作为容器类使用,因此可以调用多个重载的addView()向布局管理器中添加组件.实际上,我们完全可以用一个布局管理器嵌套到其他布局管理器中---因为布局管理器也继承了View ...
- codevs 必做:堆:1245、2879 并查集:1069、1074、1073
1245 最小的N个和 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 有两个长度为 N ...
- <2013 07 06> "极路由" 与 “家庭服务器” 报道两则
跟我做!打造家庭服务器 很久没有更新了,因为之前托朋友帮我弄的mini PC终于到手了.阴差阳错地,原来只打算弄一台将就可用的低功耗下载机,结果到手的却是一台支持1080p(宣称,还没烧过),还带遥控 ...
- 使用QtConcurrent编写多线程程序(也可以阻塞)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Amnes1a/article/details/66470751Qt在其QtConcurrent命名空 ...
- unity坑faq
遇到的坑记录下来,大都都是听说,没有实测 1. Graphics.copyTexture,在某些机型上不支持从不同类型拷贝 2. msaa 小米mix2不支持,晓龙845 3. android4.2下 ...
- MySQL中lock与latch的区分
这里要区分锁中容易令人混淆的概念lock与latch.在数据库中,lock与latch都可以成为锁,但两者有截然不同的含义 latch 一般称为闩锁(轻量级的锁) 因为其要求锁定的时间非常短,若迟勋时 ...
- python基本数据类型之操作
python注释 当行注视:# 被注释内容多行注释:""" 被注释内容 """ 字符串操作 # 代表单行注释 ...
- float 与 double
一.原因 单精度和双精度数值类型最早出现在C语言中,在C语言中单精度类型称为浮点类型(Float),顾名思义是通过浮动小数点来实现数据的存储.这两个数据类型最早是为了科学计算而产生的, 他能够给科学计 ...