记录一点结论性的东西,推导见百度吧。

首先博弈的前提是双方“绝对理智”。

一般的胜负博弈游戏来说,有以下几点:(注意必胜必败是针对这回合操作的人)

所有终结状态为必败点(比如五子棋a下出5连珠后,轮到b走,而5连珠为终结状态,所以b败,叫做必败点)。

所有1步操作能进入必败点的点为必胜点(比如该a走时a有4连珠,a只要能走出5连珠就进入了(b的)必败点,此时a必胜)。

某点的所有操作都走向必胜点,则该点为必败点。(和上一条对称)

Hdu 1517 上述定理的应用 本质还是搜索(有O(1)的数学方法)

Hdu 1079 日期模拟+博弈搜索 考验代码功底..(也有O(1)的数学方法)

可以发现,博弈的本质还是搜索,由一个局面到下一个局面,形成一颗树(或图),树的叶子节点是最终局面。

也有一些最终结果不是胜负的博弈,以https://nanti.jisuanke.com/t/19975 “Rake It In”为例(icpc现场赛题目,比赛的时候突然领悟..):

给4*4的矩阵,a,b分别进行操作,每人每次可以选择一个2*2的矩阵把他们的和加到最终分数里并逆时针旋转选中的矩阵(2人共用1个分数)。但a,b的目标不同:分别是让最终分数最大(最小)。求k轮操作最终的分数。

从第一步开始想很难,贪心显然是不行的,因为涉及矩阵的旋转,会改变整个矩阵。

但倒着想,在最后1步(最后1步是b走),b一定会选总和最小的矩阵。a走倒数第二步时知道对于每个局势b将怎么走,所以a会走最化大最小矩阵的步。

这是一个递归的过程。绝对理智走出第一步时,就把所有情节遍历了一遍,知道了最终答案。(其实并没博弈...开局就决定了胜负)

所以做法是:先遍历所有状态的分数,再递归求解绝对理智的第一步是怎么走的,就有了最终答案。(卡常数比较厉害,只能dfs,还需要一点树的知识)

或者用ab剪枝优化博弈树..

#include<cstring>

#include<cstdio>

#include<algorithm>

using namespace std;

int a[4][4], k, sum;

short num[600005], ans[66666];

void fx(int x, int y)

{

int temp = a[x][y];

a[x][y] = a[x][y + 1], a[x][y + 1] = a[x + 1][y + 1];

a[x + 1][y + 1] = a[x + 1][y], a[x + 1][y] = temp;

}

void cofx(int x, int y)

{

int temp = a[x][y];

a[x][y] = a[x + 1][y], a[x + 1][y] = a[x + 1][y + 1];

a[x + 1][y + 1] = a[x][y + 1], a[x][y + 1] = temp;

}

void dfs(int tim, int x)

{

num[x] = sum;

int i, j;

/*下一步是常数优化,注释这样写更容易懂但会tle..大概效率差了1倍

if (tim == k)

return;

*/

if (tim == k - 1)

{

for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++)

num[x * 9 + i * 3 + j + 1] =

sum + a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1];

return;

}

for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++)

{

fx(i, j);

sum += a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1];

dfs(tim + 1, x * 9 + i * 3 + j + 1);

cofx(i, j);

sum -= a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1];

}

}

int viia(int tim, int x)

{

if (tim == k)

return num[x];

if (ans[x] != -1)

return ans[x];

if ((tim & 1) == 0)

{

int te = 0;

for (int i = 1; i <= 9; i++)

te = max(te, viia(tim + 1, x * 9 + i));

return ans[x] = te;

}

else

{

int te = 999999;

for (int i = 1; i <= 9; i++)

te = min(te, viia(tim + 1, x * 9 + i));

return ans[x] = te;

}

}

int main()

{

int t, i, j;

scanf("%d", &t);

while (t--&&scanf("%d", &k))

{

sum = 0;

k <<= 1;

for (i = 0; i < 4; i++)

for (j = 0; j < 4; j++)

scanf("%d", a[i] + j);

memset(num, 0, sizeof(num));

memset(ans, -1, sizeof(ans));

dfs(0, 0);

printf("%d\n", viia(0, 0));

}

return 0;

}

博弈的搜索求解的本质是树的遍历,但博弈论(sg函数相关)是从数学角度快速求解特定类博弈问题(直接上最终结论,但墙裂推荐认真学一遍推导过程)。

针对这类问题,应用sg函数可以快速解决:

给定模型给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负。

比如给定1堆石子, 2人轮流操作,每次操作可以将某堆石子取出b[i]个,2人绝对理智,求最终谁胜。

定义对于自然数集合的mex运算,mex(A)表示A中最小的未出现的自然数

定义对于节点的sg函数,x的子节点的sg函数构成的集合为A,则sg(x)=mex(A)。(对于叶子结点x,A为空集,mex(x)=0)

则有:对于状态x,先手必败当且仅当sg(x)=0。

这样理论上可以解决所有上述类型问题,可如果有n堆石子(每一步可以在n个图中选一个图操作)当n很大是时候,节点也非常多,算sg函数基于递归,计算量仍然很大。

另一个结论是:n个有向图游戏构成的游戏其sg函数为所有子游戏sg函数的异或。

理论部分就这些,推导有点麻烦(再次墙裂推荐看一遍推导)。

以取石子https://nanti.jisuanke.com/t/25083为例:

3堆石子,每次可以取1,3,7,9个,求最终谁胜。

分解为3个1堆石子的游戏,预处理出x个石子时的sg(x),判断sg(x)^sg(y)^sg(z)是否为0即可。

#include<cstring>

#include<cstdio>

#include<algorithm>

using namespace std;

//f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理

//SG[]:0~n的SG函数值

//S[]:为x后继状态的集合

int f[] = { 1,3,7,9 }, SG[1005], S[1005];

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 <= 3; j++)

S[SG[i - f[j]]] = 1;  //将后继状态的SG函数值进行标记

for (j = 0;; j++)

if (!S[j])

{   //查询当前后继状态SG值中最小的非零值

SG[i] = j;

break;

}

}

}

int main()

{

int n, m, k;

getSG(1000);

while (~scanf("%d%d%d", &n, &m, &k))

puts(SG[n] ^ SG[m] ^ SG[k] ? "win" : "lose");

return 0;

}

对于不好打表(不是取石子这种)的模型,可以直接在图上dfs出每个节点的sg函数。

Hdu 1847 sg函数模板题目 可以发现步数是2的幂时sg(x)=0当且仅当x%3=0(所以直接判%3也行)

Hdu 1848 同上

Poj 2234 同上,可以发现对于一堆石子取任意数目时sg(x)=x。

Hdu 2509 注意胜负条件和取石子相反,先取完的输。用必胜点的方法可以发现规律。特判所有堆都是1的情况就好。

Hdu 1907 同上

博弈论与sg函数入门相关推荐

  1. 博弈论与SG函数(Nim游戏)

    博弈论与SG函数(Nim游戏) 目录 博弈论与SG函数(Nim游戏) 游戏状态 状态图(SG图) Nim 游戏 Nim 和 SG函数 Grundy数字 组合博弈游戏 Grundy 游戏 例题 在本篇, ...

  2. 算法竞赛进阶指南0x3A 博弈论之SG函数

    算法竞赛进阶指南0x3A 博弈论之SG函数

  3. 《算法竞赛进阶指南》数论篇(3)-组合计数,Lucas定理,Catalan数列,容斥原理,莫比乌斯反演,概率与数学期望,博弈论之SG函数

    文章目录 组合计数 例题:Counting swaps Lucas定理 Cnm≡Cnmodpmmodp∗Cn/pm/p(modp)C_n^m\equiv C_{n\ mod\ p}^{m\ mod\ ...

  4. Cow Digit Game(博弈论:sg函数)

    链接:https://ac.nowcoder.com/acm/contest/1071/G 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6553 ...

  5. 博弈论与 sg 函数

    博弈论 定义 必胜状态 为 先手必胜的状态 , 必败状态 为 先手必败的状态 . 通过推理,我们可以得出下面三条定理: 定理 1:没有后继状态的状态是必败状态. 定理 2:一个状态是必胜状态当且仅当存 ...

  6. 博弈论之SG函数(NIM博弈、反NIM博弈证明+例题)--POJ2311

    目录 NIM博弈: 题目: 代码: 反NIM博弈: 题目: 代码: 公平组合游戏ICG: 有向图游戏: Mex运算: SG函数: 有向图游戏的和: 定理: 题目: 代码: 参考材料: NIM博弈: 内 ...

  7. SG函数入门HDU 1848

    SG函数 sg[i]为0表示i节点先手必败. 首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数.例如mex{0,1,2,4}=3. ...

  8. hdu1847(博弈论:sg函数)

    Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...

  9. 牛客小白赛7 B自杀游戏 (博弈论,SG函数)

    链接:https://www.nowcoder.com/acm/contest/190/B 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6553 ...

最新文章

  1. AngularJS $q 和 $q.all 单个数据源和多个数据源合并(promise的说明)
  2. Oracle 检查点队列和HASH Bucket
  3. 在ubuntu上使用SSH客户端
  4. 一个linux提权用的技巧
  5. 天翼云从业认证(1.1)服务器的分类、用途、特点、结构和组件
  6. matplotlib 雷达图2
  7. Intellij代码界面导入maven工程,且该maven工程不具备intellij配置文件
  8. ubuntu16.04下安装NS-2.35以及对simple例的理解
  9. Could not load TestContextBootstrapper [null]. Specify @BootstrapWith‘s ‘value‘ attribute...
  10. 线程Thread类的start()方法和run()方法
  11. 让美团、京东、搜狐都说好的数据仓库,牛在哪?
  12. java I O类大全_Java I/O —— File类
  13. 用CSS绘制实体三角形并说明原理
  14. java jtextpane_java – 从JTextPane获取原始文本
  15. 物联网导论知识部分梳理
  16. 小样本不符合正态_尿液样本HPV分型检测用于宫颈癌筛查的可能性
  17. Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is bein
  18. 微信发红包案例测试场景
  19. w ndows无法连接到无线网络,windows无法连接到无线网络,详细教您windows无法连接到无线网络怎么办...
  20. Android 恢复出厂设置流程分析

热门文章

  1. 将对方的名字注册成殡葬行业商标?不合法!!!
  2. 拼多多TOKEN安卓登录方法
  3. 英语学习方法--听力和口语提高
  4. 永磁同步电机三相等效电路图_三相永磁同步电动机的控制电路的制作方法
  5. 量化进阶——如何进行期权套利(一)
  6. PIE-Engine:房山区洪涝灾害风险评价
  7. 安卓导航车机root方法_飞歌ES1互联网智能车机:一触即达已经OUT了!现在是一说即达...
  8. 潜在通路分析软件QA/SCAT V2.0用户使用说明书(目录)
  9. 玩转黑莓8900,不信你不会。超级实用
  10. SFP GBIC XFP SFP+光模块的区别杂谈