博弈论进阶——Anti-SG
博弈论进阶——\(Anti\)-\(SG\)
博弈\(——\)多年以后,\(Bob\)仍然爱慕着\(Alice\)的容颜
\(SG\)函数的拓展\(——Anti\)-\(SG\)游戏
感谢贾志豪《组合游戏略述——浅谈SG游戏的若干拓展及变形》一文
一、\(Anti-Nim\)游戏
有\(n\)堆石子,两个人可以从任意一堆石头中拿走任意颗石头,拿走最后一个石头的失败。
这与我们之前处理的\(Nim\)游戏有所不同,即两人胜利的条件发生了改变,与\(Nim\)游戏相反,所以被称之为反\(Nim\)游戏。
结论:
先手必胜当且仅当满足下面两种情况的一种:
(1)任意堆的石子数都为\(1\)且游戏的\(SG\)值为\(0\)
(2)存在堆的石子数大于\(1\)且游戏的\(SG\)值不为\(0\)
证明:
假设有\(n\)堆石子。
- 每堆只有一个石子
之前我们就证明过每一堆石子的\(SG\)值显然是这堆石子的个数。每一堆的石子数均为\(1\)。
很容易看出:
当有偶数堆时,也就是\(SG\)值为\(0\)时,先手必胜
当有奇数堆时,也就是\(SG\)值为\(1\)时,先手必败 - 至少两堆石子数大于\(1\)
考虑两种情况,当\(SG\)为\(0\)和\(SG\)不为\(0\)的情况。
- 当 \(SG\) 不为 \(0\) 时
若还有至少两堆石子的数目大于 \(1\),则先手将 \(SG\) 值变为 \(0\) 即可;若只有一堆石子数大于 \(1\),则先手总可以将状态变为有奇数个 \(1\)。所以,当 \(SG\) 不为 \(0\) 时先手必胜。 - 当 \(SG\) 为 \(0\) 时
至少有两堆石子的数目大于 \(1\),则先手决策完之后,必定至少有一堆的石子数大于 \(1\),且 \(SG\) 值不为 \(0\),由上段的论证我们可以发现,此时,无论先手如何决策,都只会将游戏带入先手必胜局,所以先手必败。
(说实话感觉大佬贾志豪这段的证明有点问题)
另外一种证明方式
二、\(Anti-SG\)
\(Anti-SG\)游戏与\(SG\)游戏不同的点仅仅在于\(Anti-SG\)是最后一个进行操作的输。
\(SG\)函数存在这样一个性质:
\(SG\)为\(0\)的局面不一定为终局局面。(定理一的反命题)
基于这个性质我们可以知道\(Anti-Nim\)的结论并不能直接套用在\(Anti-SG\)上面。
对于这个问题,贾志豪给出了\(SJ定理\)\((Sprague Grundy——Jia Zhihao定理)\)
\(SJ\)定理
规定当局面中所有的单一游戏\(SG\)值为\(0\)时,游戏结束,则先手必胜当且仅当
- 游戏\(SG\)值不为\(0\)且游戏中某个单一游戏的\(SG\)函数大于\(1\)
- 游戏\(SG\)函数为\(0\)且游戏中没有单一游戏的\(SG\)函数大于\(1\)
证明(全文照搬):
我们只需要证明:
- 所有的终止局面为先手必胜局。(这一点显然,证明中略去)
- 游戏中的任何一个先手必败局一定只能够转移到先手必胜局;
- 游戏中的任何一个先手必胜局一定能够转移到至少一个先手必败局。
情况一:局面的 SG 函数为 0 且游戏中某单一游戏的 SG 函数大于1。
∵当前局面的 SG 函数值为 0
又∵SG 函数性质
∴它所能转移到的任何一个局面的 SG 函数值不为 0 ①
∵当前局面的 SG 函数值为 0 且游戏中某个单一游戏的 SG 函数大于1。
∴当前局面中必定至少有 2 个单一游戏的 SG 函数大于 1。
又∵每次至多只能更改一个单一游戏的 SG 值
∴它所能转移到的任何一个局面都至少有一个单一游戏的 SG 值大于1。②
由①②得,情况一所能转移到的任何一个局面都为先手必胜局。
情况二:局面的 SG 函数不为 0 且游戏中没有单一游戏的 SG 函数大于 1。
显然,当前局面一定有奇数个游戏的 SG 函数值为 1,其余游戏的 SG函数值为 0。
- 将某个单一游戏的 SG 值更改为大于 1 的数。
∵转移前没有单一游戏的 SG 值大与 1,转移将某个单一游戏的 SG值更改为大于 1 的数。
∴转移后的局面一定有且只有一个单一游戏的 SG 值大于 1。 ③
∴后继局面的 SG 值一定不为 0。 ④
由③④得,后继局面一定为先手必胜局。 - 将某个单一游戏的 SG 值更改为 0 或 1。
∵转移是将某个 SG 值为 0 的单一游戏改成 SG 值为 1 的单一游戏,或将某个 SG 值为 1 的单一游戏改成 SG 值为 0 的单一游戏。
∴转移后的局面一定有偶数个 SG 值为 1 的单一局面且不含有 SG 值大于 1 的局面。
∴后继局面一定为先手必胜局。
情况三:局面的 SG 函数不为 0 且游戏中某个单一游戏的 SG 函数大于 1
- 局面中只有 1 个单一游戏的 SG 值大于 1。
我们选择更改 SG 值最大的单一游戏,我们可以选择将其更改成 0 或1 来保证转移后的局面有且只有奇数个 SG 值为 1 的单一游戏。
则通过这种方式转以后的局面为先手必败局。 - 局面中有至少两个单一游戏的 SG 值大于 1。
根据 SG 函数性质(2),总存在一种决策可以将后继局面的 SG 函数值变为 0 ⑤
∵局面中有至少两个单一游戏的 SG 值大于 1
又∵每次最多只能更改一个单一游戏的 SG 值
∴后继局面中至少有一个游戏的 SG 值大于 1 ⑥
由⑤⑥得,后继局面为先手必败局。
情况四:局面的 SG 函数为 0 且游戏中没有单一游戏的 SG 函数大于1。
当局面中所有单一游戏的 SG 值为 0 时,游戏结束,先手必胜。
否则,局面有且仅有偶数个 SG 值为 1 的单一游戏,其余游戏的 SG
值为 0。
我们只需将其中的某一个 SG 值为 1 的单一游戏的 SG 值变为 0,游戏
中即可出现奇数个 SG 值为 1 的单一游戏,到达先手必败局。
一道模板题
code
```cpp
#include <bitset>
#include <vector>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <map>
#include <unordered_map>
using namespace std;
using namespace std;
#define lowbit(x) x&-x
#define ll int
#define pll pair<ll,ll>
#define dob double
#define For(i,s,n) for(ll i = s;i <= n;i++)
#define mem0(a) memset(a,0,sizeof a)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a/gcd(a,b)*b
#define abs(x) x>=0?x:-x
const int N = 1e5+5;
const double eps = 1e-6;
const ll mod = 1000000007;
const ll inf = 1e9+50;
int main(){
ios::sync_with_stdio(false);
ll t;cin>>t;
while(t--){
ll n;cin>>n;
ll sum = 0,cnt = 0;
for(ll i = 1;i <= n;i++){
ll x;cin>>x;
if(x>1)cnt++;
sum^=x;
}
if((sum == 0 && cnt == 0)||(sum && cnt)) cout<<"John\n";
else cout<<"Brother\n";
}
return 0;
}
原文地址:https://www.cnblogs.com/Paranoid5/p/15207289.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决InnoDB: Table mysql/innodb_index_stats has length mismatch
- R语言中对文本数据进行主题模型topic modeling分析
- QT学习第3天:QSlider使用方法
- qt学习第2天:QRadioButtonTest+ButtonGroup单选后提示消息,QComBox
- Python使用矩阵分解法找到类似的音乐
- SpringBoot集成ELK实现日志收集实践
- python在Scikit-learn中用决策树和随机森林预测NBA获胜者
- R语言:用R语言填补缺失的数据
- R语言如何和何时使用glmnet岭回归
- r语言中对LASSO回归,Ridge岭回归和Elastic Net模型实现
- cmd里如何查看历史命令并执行
- akka-typed(10) - event-sourcing, CQRS实战
- 【每日一题】37. Sudoku Solver
- A quick introduction to innodb_ruby (2.对innodb_ruby的简单介绍)
- Webkit 内核初探