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

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

这次主要介绍两个基本模型: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 脚本开发-url解码

    url解码 by:授客 QQ:1033553122 脚本结构如下: Action.c中的代码如下: int htoi(char *s) { int value = 0; int c = 0; c = ...

  2. loadrunner11迭代录制注册账号

    1.创建一个新的web脚本 2.我们就以loadrunner自带的WebTours为例子 3.点击确定后进入Web Tours主页,点击sign up now进行注册 4.输入用户名:test,密码: ...

  3. springcloud 入门 10 (eureka高可用)

    eureka高可用: 说白了,就是加一个实例作为原实例的备份,然后一起对外提供服务.这样可以保证在一台机器宕机的时候,整个系统不会死掉.保证其继续对外服务. eureka的集群化: 服务注册中心Eur ...

  4. 安装Linux Mint 17后要做的20件事

    Linux Mint 17 Qiana Cinnamon Linux Mint 17已经发布,定名为Qiana.Mint是Linux最佳发行版之一,它定位于桌面用户,关注可用性和简洁.它携带了风格迥异 ...

  5. HDU ACM 1879 继续畅通工程

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. 第五章 绘图基础(LINEDEMO)

    LINEDEMO程序绘制一个矩形.两条直线.一个椭圆和一个圆角矩形.该程序表明,定义了封闭矩形的这些函数确实对这些区域进行了填充,因为椭圆后面的线被隐藏了. /*------------------- ...

  7. 网页中的meta标签的作用

    偶尔看到一篇博客详细介绍了meta的作用:http://www.cnblogs.com/nianshi/archive/2009/01/14/1375639.html

  8. Html body的滚动条禁止与启用

    在写一个在页面中,经验证用户没有登录或session失效时候弹出登录框禁止页面滚动用到今天搞了一个功能,上下左右居中,模仿QQ空间里的样式,把横向和纵向滚动条禁止掉代码如下:<script ty ...

  9. C#用默认浏览器打开特定网址的几种方法

    方法一:从注册表中读取默认浏览器可执行文件路径 private void button1_Click(object sender, EventArgs e) { //从注册表中读取默认浏览器可执行文件 ...

  10. Linux - CentOS7上的时间同步

    1. 时区的概念 1.1 时区简介 地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早.东边时刻与西边时刻的差值不仅要以时计,而且还要以分和秒来计算,这给人们带来不便.所以为了克服时间上 ...