目录

NIM博弈:

题目:

代码:

反NIM博弈:

题目:

代码:

公平组合游戏ICG:

有向图游戏:

Mex运算:

SG函数:

有向图游戏的和:

定理:

题目:

代码:

参考材料:


NIM博弈:

内容:给定N堆物品,第i堆物品有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。

定理:NIM博弈先手必胜,当且仅当 A1 ^ A2 ^ … ^ An != 0

证明:

若面临的局面是所有物品被取光,这时候肯定是必败局面(因为意味着对手去到了最后一件物品)。此时显然A1 ^ A2 ^ … ^ An = 0。

对于任意局面A1 ^ A2 ^ … ^ An = x != 0。x的二进制表示中最高位是k位。那么必定存在一个Ai的二进制第k位不为0。并且Ai^x<Ai(因为xor后Ai的第k位从1->0,后面无论增减注定Ai变小)

这时候我们就从Ai中取走Ai-x^Ai即可,使Ai变为Ai^x,这时候A1 ^ A2 ^ … ^ An^x = x^x = 0。

这样我们就可以时刻保持A1 ^ A2 ^ … ^ An = 0。一直到所有物品为零。

证毕。

题目:

甲,乙两个人玩 Nim 取石子游戏。

Nim 游戏的规则是这样的:地上有 nn 堆石子(每堆石子数量小于 10^4 ),
每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。
每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,
且告诉你这 n堆石子的数量,他想知道是否存在先手必胜的策略。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#include<cmath>
#include<stdlib.h>using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+50;int main(){int t;cin >> t;while(t--){int n;scanf("%d",&n);int ans = 0;int x;for(int i = 0;i < n;i++){scanf("%d",&x);ans^=x;}if(ans == 0)  puts("No");else puts("Yes");} return 0;
}

反NIM博弈:

与NIM博弈相对,相对的地方是取到最后一个石子的人输。

先手必胜定理:

一:各堆物品数目异或结果不为零,且至少有一堆物品数目大于1

二:各堆物品数目异或结果为零,且所有堆物品数目均为1;

证明:

S表示异或和不为0,T表示异或和为0。充裕堆:物品数大于等于2。

S0、S1、S2分别表示异或和不为零且充裕堆为0、1、大于等于2。T0、T2表示异或和为0且充裕堆为0 、大于等于2。

首先   显然S0必输、T0必胜。

对于S1,可以转化为S0。(若为奇数堆,拿掉充裕堆所有即可 ;若为偶数堆,拿掉充裕堆只剩下一个)。

对于T2,只可能转化为S1,或者不变。 这样T2必败。

S2可以转化为T2。所以S2必胜。

所以必胜局面:T0、S1、S2。即异或和为零且所有堆物品数全为1或者异或和不为0且至少一堆物品数大于1。

题目:

小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取
的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一
粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大的优势,所以他总是先取石子,而他的哥哥就聪明
多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。自然,你应该先写一个程序,预测一下
谁将获得游戏的胜利。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#include<cmath>
#include<stdlib.h>using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+50;int main(){int t;cin >> t;while(t--){int n;scanf("%d",&n);int x,ans = 0,cnt = 0;for(int i = 0;i < n;i++){scanf("%d",&x);if(x > 1)    cnt++;ans^=x;}//先手获胜:xor和为零且全部石堆石头个数都为1  或者  xor和不会零且至少有一个石堆大于石头个数1 //也即T0、S1、S2; if((ans&&cnt)||(!ans&&!cnt))    puts("John");else puts("Brother");} return 0;
}

公平组合游戏ICG:

若一个游戏满足:

  1. 由两名玩家交替行动;
  2. 在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关;
  3. 不能行动的玩家判负;

则称该游戏为一个公平组合游戏。

NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。

有向图游戏:

给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负。该游戏被称为有向图游戏。

任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并且从每个局面向沿着合法行动能够到达的下一个局面连有向边。

Mex运算:

设S表示一个非负整数集合。定义mex(S)为求出不属于集合S的最小非负整数的运算,即: mex(S) = min{x}, x属于自然数,且x不属于S

解释:加入S={1,2,4}  则mex{S} = 0;若S={0,1,3},则mex(S) = 2;也就是对于一个全是非负整数的集合S,它的mex值就是不包含在S中的最小非负整数。

留意的是,对于S={},mex(S) = 0;

SG函数:

在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1, y2, …, yk,定义SG(x)为x的后继节点y1, y2, …, yk 的SG函数值构成的集合再执行mex(S)运算的结果,

即: SG(x) = mex({SG(y1), SG(y2), …, SG(yk)}) 特别地,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即SG(G) = SG(s)。

有向图游戏的和:

设G1, G2, …, Gm 是m个有向图游戏。定义有向图游戏G,它的行动规则是任选某个有向图游戏Gi,并在Gi上行动一步。

G被称为有向图游戏G1, G2, …,Gm的和。 有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数值的异或和,即: SG(G) = SG(G1) ^ SG(G2) ^ …^ SG(Gm)

定理:

有向图游戏的某个局面必胜,当且仅当该局面对应节点的SG函数值大于0。

有向图游戏的某个局面必败,当且仅当该局面对应节点的SG函数值等于0。

部分理解:

若之后无路可走,S = {};此时mex(S) = 0;所以肯定是必败的。

若一个节点的某个后继节点(即局面)SG值为0,那么mex(S) > 0   <=>   若一个局面的后继局面存在必败局面,则当前局面为必胜局面。

// 存在必败局面,那么我们就把这个局面推向必败局面给对手即可。

若一个结点的后继节点全部大于零,那么mex(S) = 0  <=>  若一个局面的后继局面全部是必胜局面,则当前局面为必败局面。

//都是必胜局面,那么我们无论怎么做都把必胜局面给了对手。

题目:

Urej 喜欢玩各种类型的沉闷游戏。他通常要求别人和他一起玩。
他说,玩这些游戏可以展示他非凡的智慧。
最近,乌雷杰对一款新游戏非常感兴趣,埃里夫·内佐夫成为受害者。
为了摆脱玩这种沉闷游戏的痛苦,埃里夫·内佐夫请求你的帮助。
游戏使用由 W*H 网格组成的矩形纸。两个玩家依次将纸张切成两块矩形部分。
在每一个回合中,玩家都可以水平或垂直切割,保持每个网格不间断。
N 转后,纸张将分解成 N+1 件,在以后的回合中,玩家可以选择任何要切割的纸张。
如果一个玩家用一个网格剪掉一张纸,他就赢了比赛。
如果这两个人都很清楚,你应该写一个问题,告诉一个谁先削减可以赢与否。

必败局面,也就是有向图的终点:不存在大于等于4的边。这时候无论怎么捡都会出现1*X或者X*1的局面,这时候SG值肯定为0。利用递归即可。(记忆化优化)

每个局面下面的局面种类情况无非就是顺着所有的横边竖边剪掉。利用有向图游戏的和异或起来。

代码:

(参考https://blog.csdn.net/acm_zl/article/details/9447069)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#include<cmath>
#include<stdlib.h>using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+50;
int sg[255][255];
int get_sg(int n,int m){if(sg[n][m] != -1) return sg[n][m];int vis[800] = {0};//mex(S) 1 为S集合内的 0为S集合外的 for(int i = 2;i <= n-i;i++)        vis[get_sg(i,m)^get_sg(n-i,m)] = 1;for(int i = 2;i <= m-i;i++)      vis[get_sg(n,i)^get_sg(n,m-i)] = 1;//这里控制了每条边只要存在比4小的 肯定必败 也就是最后返回0; for(int i = 0;;i++)if(vis[i] == 0)       return sg[n][m] = i;// sg[n][m]为mex(S);
}
int main(){int n,m;memset(sg,-1,sizeof(sg));while(scanf("%d%d",&n,&m) != EOF){if(get_sg(n,m)){puts("WIN");}else puts("LOSE");}return 0;
}

参考材料:

《算法竞赛进阶指南》   李煜东

博弈论之SG函数(NIM博弈、反NIM博弈证明+例题)--POJ2311相关推荐

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

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

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

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

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

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

  4. 博弈论与 sg 函数

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

  5. 博弈论与sg函数入门

    记录一点结论性的东西,推导见百度吧. 首先博弈的前提是双方"绝对理智". 一般的胜负博弈游戏来说,有以下几点:(注意必胜必败是针对这回合操作的人) 所有终结状态为必败点(比如五子棋 ...

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

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

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

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

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

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

  9. [博弈论] Nim游戏及SG函数(经典+台阶+集合+拆分)

    文章目录 0. 前言 1. Nim 游戏+模板题 2. 台阶 - Nim 游戏+变种题 3. Mex运算与SG函数 4. 集合 - Nim 游戏+变种题 5. 拆分 - Nim 游戏+变种题 0. 前 ...

最新文章

  1. matlab 图像函数以及运用(第十章)
  2. 05 | 数组:为什么很多编程语言中数组都从0开始编号?
  3. 大数据、云计算、AI大牛都在这里了,就等你来捞干货
  4. matlab计算曲线形心,并将y轴移动到形心上,使图形居中布置
  5. 力扣剑指 Offer 17. 打印从1到最大的n位数
  6. CSRankings 学术机构排行榜:“三巨头”不可撼动,清华大学突围 AI 榜单!
  7. jfreechart环形图完美实现
  8. Makefile,Shell command,Shell Language 之间的联系
  9. D3D12渲染技术概述
  10. ffmpeg实现摄像头拉流_ffmpeg推流及拉流
  11. 计算机出现测试模式,win10系统右下角显示测试模式内部版本10601的详细步骤
  12. 3d建模和计算机专业对口吗,学3d建模有学历门槛吗
  13. 【MySQL学习笔记】电子杂志订阅表的操作
  14. matlab矩形滤波器,MATLAB结合矩形窗设计FIR滤波器
  15. python人民币和美元转换-Python实现制度转换(货币,温度,长度)
  16. 合作模式歌利亚机器人_《歌利亚》画面战斗及机器人制作试玩图文心得 歌利亚好玩吗...
  17. 802.11ax分析1---IEEE 802.11ax和IEEE 802.11ac性能对比
  18. 手机拍照技巧:全景拍摄,让手机拍出的照片妙趣横生
  19. 2018.11.22
  20. .NET5 安装使用

热门文章

  1. jQuery动画实现图片无缝连续自动滚动
  2. 泪水与汗水 ,我互联网创业这几年(必看)!
  3. 从虚机到容器,秒拍架构师告诉你如何平滑进行业务迁移
  4. html短信发送的方法
  5. 获5.3亿美金融资,亚马逊、红杉入局,自动驾驶“梦之队”Aurora还藏了哪些秘招?...
  6. 15个专业的基本技能
  7. 腾讯云产品系列(一)COS对象存储上传
  8. 笔记——机器学习入门
  9. 环信大学:12306十年填坑路对客户中心智能化变革的启示
  10. C语言学习:简单的小游戏 走迷宫、推箱子