最近在数学这一块搞了蛮多题目,已经解决了数论基础,线性代数(只有矩阵,行列式待坑),组合数学中的一些简单问题。所以接下来不可避免的对博弈论这一哲学大坑开工。

当然,由于我很菜,所以也只能从最基础最容易的部分讲起了。

这次主要介绍两个基本模型:Bash Game&&Nim Game,还是比较经典的

下面开始讲

1.Bash Game

Bash Game(巴什博弈)是一种零基础的入门题目,它的基本模型大概是这样的:

一堆石子共n个,两人轮流从中取石子,规定每次至少取一个,最多取m个,最后取光者得胜。问两人博弈,他们都采用最聪明的策略,问最后谁可以必胜。

首先我们从小开始分析:

  • 当m>=n时,先手可以一把抓完石子,这样先手必胜

  • 当n=m+1时,先手无论怎么抓,都会留下1~m个石子,这样后手一把就可以抓完,这样先手必败

  • 当m+1<n<2*(m+1)时,先手只要抓适当的石子就可以剩下m+1个石子,然后后手必输,那么先手必胜

  • 当n=2*(m+1)时,后手可以采取这种策略,当先手抓x个时,后手就抓m+1-x个,这样就会把m+1的情况送给先手,那么先手必败

  • ......

所以通过上面的分析我们很容易得出:当n%(m+1)==0时,先手必败;否则先手必胜

这个很简单吧,因为谁先面对k*(m+1)(k为正整数)这种局面就必定失败。因为一方可以每次让你们两个取得石子和为m+1导致另一方失败。

这个问题还有一些变形,比较经典的就是:把一个数从0开始不断增加,每次增加的范围都是1~k,谁先让数增加到n就Win||Lose

这个直接转化为Bash Game做一下即可

这里给几道例题&&CODE(以下例题都来自HDU)

1846

Bash博弈的板子题,直接上即可

CODE

#include<cstdio>
using namespace std;
int t,n,m;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
read(t);
while (t--)
{
read(n); read(m);
puts(n%(m+1)?"first":"second");
}
return 0;
}

2149

这就是那种变式的情况,我们转化一下在做转化个屁,至于输出方案的话特判一下即可

CODE

#include<cstdio>
using namespace std;
int n,m;
inline void write(int x)
{
if (x/10) write(x/10);
putchar(x%10+'0');
}
int main()
{
register int i;
while (scanf("%d%d",&m,&n)!=EOF)
{
if (n>=m)
{
for (i=m;i<n;++i)
write(i),putchar(' '); write(n); putchar('\n');
} else
if (m%(n+1)) write(m%(n+1)),putchar('\n'); else puts("none");
}
return 0;
}

2138

同上,Bash Game直接上即可

CODE

#include<cstdio>
using namespace std;
int t,n,m;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
read(t);
while (t--)
{
read(n); read(m);
puts(n%(m+1)?"Grass":"Rabbit");
}
return 0;
}

4764

这道题就注意一下大于等于n你就输了,所以n要减一

CODE

#include<cstdio>
using namespace std;
int n,m;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (;;)
{
read(n); read(m);
if (!n&&!m) break;
puts((n-1)%(m+1)?"Tang":"Jiang");
}
return 0;
}

2.Nim Game

这其实是Bash Game的进化版,但是思维深度上了好几个台阶

首先我们看基本模型:

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

这是不是很复杂,首先我们考虑数据小的情况:

  • 只有一堆石子时,除非没有石子,否则先手一把抓完即可

  • 有两堆石子时,后手只需要跟随先手的动作即可

  • ......(后面的根本分析不出来好吧)

但是在我们之前已经有大神成功证明了一个神奇的结论:

当n堆石子的数量异或和等于0时,先手必败,否则先手必胜

证明请移步至attack dalao's blog

很懵逼对吗其实我也是,那么让我们来感性理解一下(以下的说明仅为个人理解,几乎没有任何理论依据,请选择阅读)

首先由于全部都是0的时候就失败了,所以我们可以认为当它们的异或和为0就是必败态

这样我们先手是如果异或和为0那么就输了

如果不是呢,我们就可以通过一种猥琐的方法来获胜(就是上面讲的方法)

我们可以形象地认为它与Bash Game中先手先取得只剩下k*(m+1)然后通过让和始终为m+1来取胜

然后这就是神奇的Nim Game

这里有一道模板题Luogu P2197 nim游戏

由于就是裸的Nim Game,这里就直接上CODE了

#include<cstdio>
using namespace std;
int t,n,x,tot;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(t);
while (t--)
{
for (read(n),tot=0,i=1;i<=n;++i)
read(x),tot^=x;
puts(tot?"Yes":"No");
}
return 0;
}

当然这只是博弈论的入门,一些真正强力的东西如SG函数&&MINMAX等东西还是一脸懵逼

浅谈博弈论中的两个基本模型——Bash Game&&Nim Game的更多相关文章

  1. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  2. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  5. 转【】浅谈sql中的in与not in,exists与not exists的区别_

    浅谈sql中的in与not in,exists与not exists的区别   1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...

  6. 浅谈iOS中的userAgent

    浅谈iOS中的userAgent   User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...

  7. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  8. 浅谈sql中的in与not in,exists与not exists的区别

    转 浅谈sql中的in与not in,exists与not exists的区别   12月12日北京OSC源创会 —— 开源技术的年终盛典 »   sql exists in 1.in和exists ...

  9. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

随机推荐

  1. loadrunner 场景设计-集合点设置

    场景设计-集合点设置 by:授客 QQ:1033553122 1  作用 通过让多用户在同一时间点上进行并发操作来测试系统的并发处理的能力 2  实现 通过集合点函数来实现. 注意:集合点经常和事务结 ...

  2. Apache的配置详解 带图

    对Apache 的 Http.conf 各项配置详解 1.01 ServerRoot 配置 [ServerRoot "" 主要用于指定 Apache 的安装路径,此选项参数值在安装 ...

  3. domain or business logic

    Here are a few of the questions you should ask when writing business logic: ¡Do you fully understand ...

  4. python——虚拟环境之virtualenv(windows10,64位)

    1 问题 当我们拥有两个甚至多个项目A.B.C......,各个项目正常运行需求的python运行环境都不相同.而默认情况下,不管哪个项目,使用的都是全局的Python环境.上述情况,造成的问题就是, ...

  5. 使用vue的v-for生成table , 给table加上序号

    现在有一个使用mybatis的分页插件生成的table,table中数据是通过vue获得的 , 前台显示使用<tr v-for="item in items"> 后台v ...

  6. React路由 + 绝对路径引用

    路由: 哈希路由(在url地址后加   #name) // 实现页面监听 window.onhashchange = function(){ console.log(‘hash:’,window.lo ...

  7. 报数的golang实现

    报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: . . . . . 1 被读作 "one 1" ("一个一") , 即 11 ...

  8. PostgreSQL 空间处理函数

    PostGIS中的常用函数 以下内容包括比较多的尖括号,发布到blogger的时候会显示不正常,内容太多我也无暇一个个手动改代码,因此如有问题就去参考PostGIS官方文档. 首先需要说明一下,这里许 ...

  9. Django Form ModelForm modelfromset

    forms 组件 Form 组件 form表单完成的事情 提供input可以提交数据 对提交的数据进行校验 提供错误提示 定义form组件 from django import forms class ...

  10. socket 总结

    网络编程之进程:http://www.cnblogs.com/1a2a/p/7428759.html 网络编程之进阶:http://www.cnblogs.com/1a2a/p/7444446.htm ...