转自:http://blog.csdn.net/luomingjun12315/article/details/45555495

在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧.

必胜点和必败点的概念:
P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败。
N点:必胜点,处于此情况下,双方操作均正确的情况下必胜。
必胜点和必败点的性质:
1、所有终结点是 必败点 P 。(我们以此为基本前提进行推理,换句话说,我们以此为假设)
2、从任何必胜点N 操作,至少有一种方式可以进入必败点 P。
3、无论如何操作,必败点P 都只能进入 必胜点 N。
我们研究必胜点和必败点的目的时间为题进行简化,有助于我们的分析。通常我们分析必胜点和必败点都是以终结点进行逆序分析。我们以hdu 1847 Good Luck in CET-4 Everybody!为例:
当 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来分析,有没有觉得问题变简单了。
现在给你一个稍微复杂一点点的: hdu 2147 kiki's game

现在我们就来介绍今天的主角吧。组合游戏的和通常是很复杂的,但是有一种新工具,可以使组合问题变得简单————SG函数和SG定理。

Sprague-Grundy定理(SG定理):

游戏和的SG函数等于各个游戏SG函数的Nim和。这样就可以将每一个子游戏分而治之,从而简化了问题。而Bouton定理就是Sprague-Grundy定理在Nim游戏中的直接应用,因为单堆的Nim游戏 SG函数满足 SG(x) = x。不知道Nim游戏的请移步:这里

SG函数:

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如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函数的终态为 SG(x) = 0,当且仅当 x 为必败点P时。

【实例】取石子问题

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

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  8....

SG[x]    0  1  0  1  2  3  2  0  1....

由上述实例我们就可以得到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;  }  }
}  

实现上述取石子游戏:

#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
const int MAXN = 10000 + 7;
int sg[MAXN];     // Station i must lose iff sg[i] = 0, or i win
int subseq[MAXN]; // Recording subsequence of station i
int pick[MAXN];   // Ways to change station
int n, m;
void getSg(int n) { // Get all sg between 1 to nmemset(sg, 0, sizeof(sg));for(int i = 1; i <= n; ++i) {memset(subseq, 0, sizeof(subseq));for(int j = 0; pick[j] <= i && j <= m; ++j) {subseq[sg[i-pick[j]]] = 1;  // Change pick[i] from u so that u-pick[i] is a subsequence to u}for(int j = 0; ; ++j) {if(!subseq[j]) {        // i is the first non-negetive number of u's subsequencesg[i] = j;break;}}}
} int main()
{ios::sync_with_stdio(false);while(cin >> n >> m) {for(int i = 0; i < m; ++i) cin >> pick[i];getSg(n);if(sg[n]) cout << "Win" << endl;else cout << "Lose" << endl;}return 0;
}

dfs递归求sg值:

int sg[MAXN];
vector<int> gra[MAXN]; // 邻接表建立拓扑图int dfs(int a) {if(sg[a] >= 0) return sg[a];int subSeq[MAXN] = {0};for(int j = 0; j < gra[a].size(); ++j) {sg[gra[a][j]] = dfs(gra[a][j]); // 递归求后继sg值subSeq[sg[gra[a][j]]] = 1;      // 标记后继状态}for(int i = 0; ; ++i) {if(!subSeq[i]) {return sg[a] = i;               // mex函数定义}}};

博弈 - SG函数和SG定理相关推荐

  1. 组合博弈游戏 - SG函数和SG定理

    转载来自:http://blog.csdn.net/luomingjun12315/article/details/45555495 在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜 ...

  2. 三个常见博弈游戏以及 SG 函数和 SG 定理

    前言 原文章 通过数论或者自然数性质完美解决的三个常见博弈游戏: 博弈 解决方法 Bash Game 同余理论 Nim Game 异或理论 Wythoff Game 黄金分割 Bash Game 描述 ...

  3. (转载)--SG函数和SG定理【详解】

    在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正 ...

  4. 组合游戏 - SG函数和SG定理

    在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正 ...

  5. SG函数和SG定理【详解】

    在介绍SG函数和SG定理之前我们先介绍介绍必胜点与必败点吧. 必胜点和必败点的概念: P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败. N点:必胜点,处于此情况下,双方操作均正 ...

  6. SG函数和SG定理的运用

    SG函数和SG定理的运用 SG函数和SG定理常用于解决博弈论的相关问题.其中SG函数的求解主要根据MEX运算.什么是MEX运算?MEX( minimal excludant ) 字面上意思是最小除外的 ...

  7. 博弈论-SG函数和SG定理

    1.SG函数和SG定理是一个十分神奇的东西,有了它,绝大部分的博弈都可以被统一到这个上面,都可以使用SG函数解决.是一种解决博弈问题的十分方便的手段. 2.首先给出一些基本的定义:mex运算,这个是作 ...

  8. SG函数和SG定理(Sprague_Grundy)

    一.必胜点和必败点的概念 P点:必败点,换而言之,就是谁处于此位置,则在双方操作正确的情况下必败.        N点:必胜点,处于此情况下,双方操作均正确的情况下必胜. 必胜点和必败点的性质:    ...

  9. (组合游戏)SG函数与SG定理详解

    文章目录 前言 什么是组合游戏 必胜点和必败点的概念 Sprague-Grundy(SG)定理 SG函数 前言   好久没写博客了,上一篇博客还是去年实训写的,一是因为寒假,二是因为随着难度的加深,学 ...

  10. 再谈SG函数和SG定理

    今天考了一道博弈论的题,让我重新复习一下SG定理吧. 首先通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是"选择一堆石子并拿走若干颗(不能不拿)" ...

最新文章

  1. centos删除系统自带的httpd
  2. 安卓问题总结一(The connection to adb is down)
  3. Android中线程同步之Mutex与Condtion的用法
  4. js调试,输出函数调用顺序
  5. Linux环境下gcc编译链接库-lz -lrt -lm -lc都是什么库?
  6. git本地ben远程分支_git 本地分支与远程分支
  7. 【比较面】真核生物和原核生物的异同
  8. 【玩转cocos2d-x之九】动作类CCAction
  9. CCF NOI1123 A-B
  10. ssm使用全注解实现增删改查案例——DeptServiceImpl
  11. git 查看某些文档的历史版本_Git 教程(二)log 命令的使用
  12. 2019上半年这10本新书,技术大牛们都在追着看
  13. hdu 2523 SORT AGAIN
  14. c语言编译器环境,C语言教程:C环境设置
  15. 小京东商城用什么版本的php,最新2018小京东多用户通用商城网源码商城带手机版ecshop源码程序...
  16. ecshop源码教程第2季
  17. 框架分析--框架的类关系图
  18. 网络 DNS 解析与CDN加速
  19. [杜撰的故事]那天以后
  20. Visual Servo Control Part I: Basic Approaches

热门文章

  1. ubuntu18.04 虚拟机重启后变成只读模式,怎么恢复?
  2. 联发科MTK工程模式(中文对照版本)和测试模式指令
  3. HTML布局之flex布局
  4. android 相对布局(RelativeLayout)
  5. 一、时间序列(1)资产收益率、随机过程、白噪声序列定义
  6. 都说程序员秃头996,你见过游戏3D建模师爆肝007吗?
  7. 直播购物平台应开发的功能
  8. FPGA VHDL 驱动群创 TFT LCD AT070TN92
  9. Shell 进阶指南
  10. python单因素方差分析_Python数据科学:方差分析