博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈博弈论-ICG篇
阅读量:4047 次
发布时间:2019-05-25

本文共 3210 字,大约阅读时间需要 10 分钟。

公平组合游戏(ICG)

定义

游戏由同样很聪明的两个人 参与,二者轮流做出决策,且都会做出最有利于自己的决策,当有一人无法做出决策时(即无法行动)游戏结束,无法做出决策的人输。

无论二者如何做出决策,游戏可以在有限步内结束
游戏中的同一个状态不可能多次抵达。且游戏不会有平局出现
任意一个游戏者在某一确定状态可以作出的决策集合只与当前的状态有关,而与游戏者无关。

比如:Nim游戏

Nim游戏

取 石 子 游 戏

桌子上有N堆石子,每一堆石头有ai个,两人轮流取石子。

每次只能从一堆中取出任意数目的石子,但不能不取。 取走最后一个石子者胜。

结论:

先手必败:a1 ^ a2 ^ a3 ^ … ^an = 0

那么先手必胜就是上述结果不为0

证明:

使用不严谨数学归纳法:

1.最终状态下,异或和为0

2.对于异或和不为0的状态,取剩余石头最多的一堆,使其的剩余数量 等于其余石头堆每堆石头数量的异或和,这样整体的异或和就又成为0了

3.对于异或和为0的状态,分为两种,一种是情况1,即已经没有石头了;第二种,还有石头,那么无论怎么取,都会使整体异或和不为0(取某一堆的石头等效于让这堆石

头异或上某个不为0的数,而整体异或和为0,0异或一个不为0的数,那么结果一定不为0)

不难发现,只要双方都采取最优策略,那么先手或后手面对的局面(即异或和是否为0)会一直持续下去,直至游戏结束。

SG函数

我们把每一个游戏状态抽象成一个自然数值,称之为该状态的SG函数值,且最终状态的SG函数值为0

且定义以下递进关系:SG(u) = mex(SG(v) | v为所有u的后继状态)

其中mex(minimal excludant)是一种运算,其运算结果为不在这个集合中,最小的自然数。

比如:mex(1,3,4) = 0; mex(0,1,2,4) = 3; mex(0,1,0,2) = 3。

结论:

必败态的SG值为0,必胜状态SG值不为0

证明:

同样使用不严谨数学归纳法:

1.结束状态(必败状态)的SG函数值为0

2.当前状态的SG值不为0,说明后继状态有SG函数值为0的,那么我们可以走到那个状态(即将SG为0的状态,即必败状态给对手)

3.当前状态的SG值为0,说明后继状态的SG函数函数值均不为0,那么我们无论怎么走,都会把SG函数值不为0的状态,即必胜状态给对手

例子:

考虑有一堆石头,一共有n个,两个人轮流取,每次只能取1个或者2个,不能不取,谁先取完谁赢(注意这句话与 谁先不能取谁输 等效)。

那么我们定义如下SG函数:

SG(x), 其中x为剩余的石头数量(即当前的游戏状态),

那么很显然,当x >= 2时,SG(x) = mex(SG(x-1), SG(x-2)); SG(0) = 0;SG(1) = mex(SG(0)) = 1。

那么我们可以进行运算: SG(2) = mex(SG(0), SG(1)) = 2。表示有2个石头的时候,先手必胜(与直觉相同)

SG(3) = mex(SG(2), SG(1)) = mex(2, 1) = 0。表示有3个石头的时候,先手必败。(无论先手取一个还是两个,后手都能把剩下石头取完)

SG(4) = mex(SG(3), SG(2)) = mex(0, 2) = 1。表示有4个石头的时候,先手必胜。(我们可以取1个,对手面临”先手,有3个石头的必败局面“,这与刚才证明阶段的

”当前状态SG值不为0时,则存在后继状态的SG值为0“ 相吻合,而我们说 两个人都会做出最有利于自己的决策,就是为了保证那个人会做出”把必败局面给对手”的决策)

另外我们容易看出来,不同状态的SG函数可能相同(只是说明有这个现象,具体意味着什么本蒟蒻还不清楚orz)。

**进阶:**可以把条件改为一次可以取1,2,3个,再进行mex运算,看看结果会如何~~(实在是肝不动了,偷个懒)~~。

SG定理

应用场景:

SG定理用于多个同时进行的SG函数的游戏,就比如刚才的Nim游戏,每一堆石子,都存在自己的且与其他堆无关的SG函数。

如果把刚才例子中的一堆石子变为多堆石子,那么同样就是要利用SG定理。

内容:

假设当前游戏局面X由子游戏局面X1,X2,…Xn组成,那么SG(X) = SG(X1) ^ SG(X2) ^ … ^ SG(Xn)

(用Nim游戏举例,子游戏局面的SG值就相当于每一堆的石子的SG函数值)

证明:

我们使用"类比证明法"(当然这是不严谨的,因为本蒟蒻不会QAQ)

对于当前游戏局面的任意一个子局面的SG函数,假设为ai,那么显然表明,它的后继状态的SG值可以取0到ai-1,然后率先让所有子局面的SG值都为0的人就会胜利…

等等!!!这不是和刚才的取石子游戏一样嘛!!!所以就能直接套用这个模板啦!!

一些启发:

所以拿到一个题目后,如果我们决定要使用SG函数来做,那么就要先分清楚子局面和后继状态:子局面内部SG函数是用mex运算,而子局面之间的运算则是异或。

例题:

POJ - 2311

题目大意:

给定一个有nm格子的纸片,两个人轮流剪,只能沿着格子的线直线剪。率先剪出11格子的人胜利。给定n和m,问先手是否必胜。

分析:

假设当前是nm的,那么考虑它的后继状态,假设我们把它剪成 nr,n*(m-r)两个纸片,会发现,它的后继状态是由两个子状态构成的!

所以SG(n,m)的这个后继状态的SG值应该是由SG(n,r)和nSG(n,m-r)这两个子局面的SG值异或得到的

除了这种剪法,我们还有其它的剪法,而SG(n,m)的值就是对它的后继状态取mex操作后得到的。

代码:

(见代码中的标注)

0.这就是在进行各种剪法,即后继状态,而后继状态是由多个子局面组成的,所以这个后继状态的SG值是子局面的异或和。

1.这是在求mex运算,vis[x]记录的是当前状态的后继节点的SG值是否有为x的。

2.SG初始化一定不能为0,因为有的时候,SG函数的值本来就是0。

#include 
#include
#include
using namespace std;const int maxN = 205;int sg[maxN][maxN];int SG(int r, int c){
if(sg[r][c] != -1) return sg[r][c]; int vis[51]; memset(vis, 0, sizeof vis); for(int i = 2; i <= r - i; ++i)//0. vis[SG(i, c) ^ SG(r - i, c)] = 1; for(int i = 2; i <= c - i; ++i) vis[SG(r, i) ^ SG(r, c - i)] = 1; sg[r][c] = 0; while(vis[sg[r][c]])// 1. ++sg[r][c]; return sg[c][r] = sg[r][c];}int main(){
int n, m; memset(sg, -1, sizeof sg);//2. while(~scanf("%d%d", &n, &m)) {
if(SG(n, m) > 0) printf("WIN\n"); else printf("LOSE\n"); } return 0;}

希望蒟蒻的这篇博客对你有帮助orz

转载地址:http://ruuci.baihongyu.com/

你可能感兴趣的文章
[互联网学习]如何提高网站的GooglePR值
查看>>
[关注大学生]求职不可不知——怎样的大学生不受欢迎
查看>>
[关注大学生]读“贫困大学生的自白”
查看>>
[互联网关注]李开复教大学生回答如何学好编程
查看>>
[关注大学生]李开复给中国计算机系大学生的7点建议
查看>>
[茶余饭后]10大毕业生必听得歌曲
查看>>
gdb调试命令的三种调试方式和简单命令介绍
查看>>
C++程序员的几种境界
查看>>
VC++ MFC SQL ADO数据库访问技术使用的基本步骤及方法
查看>>
VUE-Vue.js之$refs,父组件访问、修改子组件中 的数据
查看>>
Vue-子组件改变父级组件的信息
查看>>
Python自动化之pytest常用插件
查看>>
Python自动化之pytest框架使用详解
查看>>
【正则表达式】以个人的理解帮助大家认识正则表达式
查看>>
性能调优之iostat命令详解
查看>>
性能调优之iftop命令详解
查看>>
非关系型数据库(nosql)介绍
查看>>
移动端自动化测试-Windows-Android-Appium环境搭建
查看>>
Xpath使用方法
查看>>
移动端自动化测试-Mac-IOS-Appium环境搭建
查看>>