数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」争先恐后地博弈

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

博弈论基础

    博弈论又被称为对策论(Game Theory),既是现代数学的一个新分支,也是运筹学的一个重要学科。博弈论主要研究公式化了的激励结构间的相互作用,是研究具有斗争或竞争性质现象的数学理论和方法。博弈论考虑游戏中的个体的预测行为和实际行为,并研究它们的优化策略

引入:囚徒困境

    囚徒困境的故事讲的是,两个嫌疑犯小A、小B作案后被警察抓住,分别关在不同的屋子里接受审讯。警察知道两人有罪,但缺乏足够的证据。警察告诉每个人:如果两人都抵赖,各判刑一年;如果两人都坦白,各判五年;如果两人中一个坦白而另一个抵赖,坦白的放出去,抵赖的判十年

于是,每个囚徒都面临两种选择:坦白或抵赖。

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

    在不和小B商量的情况下,作为小A的你是选择招供坐牢5年或0年,还是会选择抵赖坐牢10年或1年呢?

                                        数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

一般的人都会选着保险一点的招供吧。

    反观小B,也一定会做出同样的选择,也就是招供。换句话说,只要两名囚徒都是自私且理性的,那么双方都会同时选择招供,结果就是双方各判5年。

    在这个场景中,双方都无法单方面改变自己的博弈策略(单方面改变只会让自己蒙受损失),使得局面进入了一个微妙而又稳定的平衡,这个平衡被称为纳什均衡

    在现实中,也有很多类似的现象,比如家长给孩子报越来越多的课外班,比如高三考生备战高考,起来了啊.从局外人看来,许多竞争都是显而易见双输的局面,但是我们没有办法,因为我们都是参与博弈的“囚徒”。

ICG博弈

所讨论的博弈问题满足以下条件:

    玩家只有两个人轮流做出决策。

    游戏的状态集有限,保证游戏在有限步后结束,这样必然会产生不能操作者,其输。

    对任何一种局面,胜负只决定于局面本身,而与轮到哪位选手无关。

取石子游戏:取石子游戏是一个古老的博弈游戏,发源于中国,它是组合数学领域的一个经典问题。它有许多不同的玩法,基本上是两个玩家,玩的形式是轮流抓石子,胜利的标准是抓走最后的石子玩家设定: 先取石子的是玩家A(先手A),后取石子的是玩家B(后手B)。

经典的三种玩法

一、巴什博奕(Bash Game)

二、尼姆博奕(Nimm Game)

三、威佐夫博奕(Wythoff Game)

(一)巴什博弈

1堆n个石子每次最多取m个、至少取1个

Case 1:如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜

Case 2:n=(m+1)*r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后者拿走k(1≤k≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜

Case 3:n=r*(m+1),先手拿走k(1≤k≤m)个,那么后手再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,则后手胜,先手必败

总之,要保持给对手留下(m+1)的倍数,就能最后获胜。

术语:正经人称(m+1)的局面为奇异局势

变相的玩法

两个人轮流报数,每次至少报一个,最多报十个,谁能报到100者胜。(等价于从一堆100个石子中取石子,最后取完的胜)

例题:2368 — Buttons (poj.org)

题面:

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

      题面意思:有一堆k个的石头,每人轮流拿1,2,..L个石头,数据范围是3 <= K <= 100 000 000 ,2 <= L < K。输入k的值,要求输出最小的L,使得后者胜。

在理解了巴什博弈之后来看这题还是思路比较清晰的,首先想让后手胜,就必须把(1+L)的局面留给先手。这题没问我们谁会赢,问的是后手要赢的最小L值为多少。那我们就找到能被k整除的最小大于2的因数,之后减1输出就是答案了。

于是有了以下代码注意下(poj用不了万能头文件,编译器要求有点严格。):

//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=100005;
ll n;//石子数量
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    ll i;
    for(i=2;i<n;i++)//依次找最小的因子
    {
        if(n%(i+1)==0)
        {
            cout<<i<<endl;
            break;
        }
    }
    if(i==n) cout<<0<<endl;//找不到的情况下输出0
    return 0;
}

 就是说数据范围1e8,就超时快乐,TEL了哈哈哈哈哈哈。由于循环2~n,时间复杂度是O(n)。

    再有一个新的思路就是,遍历一遍所有的n的因数,存起来,在输出最小大于等于3的因数减一。一下代码时间复杂度为O(log n)。AC快乐。

//#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll n,a[N];//n为石头总数,a[i]存n的因数
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    int temp=0;
    for(int i=1;i*i<=n;i++)
    {
        if(n%i==0&&i*i!=n) a[temp++]=i,a[temp++]=n/i;
        //注意要区别开类似n=4时,因数为1,2,4.而不是1,2,2,4的情况
        else if(n%i==0&&i*i==n) a[temp++]=i;
    }
    sort(a,a+temp);//从小到大排序一下
    for(int i=0;i<temp;i++)
    {
        if(a[i]>=3)//找到最小大于等于3的因数,减一输出
        {
            cout<<a[i]-1<<endl;
            break;
        }
    }
    return 0;
}

(二)尼姆博弈

有n堆石子,每堆石子的数量是a1,a2,a3……,二个人依次从这些石子堆中的一个拿取任意的石子至少一个,最后一个拿光石子的人胜利

n=1: 先手全拿,先手必胜。

n=2:有两种情况,一种可能相同,一种情况一堆比另一堆少(多)

        (m,m) 按照“有一学一,照猫画猫”法,先手必输。

        (m,M)先手先从多的一堆中拿出(M-m)个,此时后手面对(m,m)的局面先手必胜。

术语:正经人称(m,m)的局面为奇异局势

n=3:(m,m,M)先手必胜局,先手可以先拿M,之后变成了(m,m,0)的局面,是不是很熟悉~

 (a1,a2,a3)的话,举个例子(1,2,3),先手取完之后可能的局面为(0,2,3),(1,1,3),(1,0,3),(1,2,2),(1,2,1),(1,2,0)都是之前讲过的,情况如下:

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

 数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

前人告诉我们的规律是:异或的结果均为0

获胜情况的讨论

面对异或结果为0的玩家必输。

结果不为0,则玩家有获胜的取法。

例题:891. Nim游戏 – AcWing题库

 题面:

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

看懂了尼姆博奕,这个题目就是分分钟AC咯。

上代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll n,a[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    int ans=a[0];
    for(int i=1;i<n;i++) ans^=a[i];//^就是做异或运算
    if(ans==0) cout<<"No"<<endl;
    else cout<<"Yes"<<endl;
    return 0;
}

(三)威佐夫博弈

有两堆各若干个物品,两个人轮流从任一堆取至少一个同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

举一个例子:局势是(1,2),先手有四种取法,动动你聪明的脑子就会发现无论先手怎么取,后手都能胜利,也就是说(1,2)是奇异局势。

没脑子的人来看看分析咯:

先手从第一堆里面拿1个,后者拿光后面的2个,后者胜。

先手从第一堆和第二堆里面同时拿1个,后者只能拿走第二堆剩下的1个,后者胜。

先手从第二堆里面拿2个,后手拿走第一堆的1个,后者胜.

先手从第二堆里面拿1个,后手从第一堆和第二堆里面同时拿走1个,后者胜。

假设现在的局势是(3,5):

(1)先手在“3”中取1个,后手就可以在“5”中取走4个,这样就变成了(1,2)的局势

(2)先手在“3”中取2个,后手就可以在 “5” 中取走3个,这样也变成了(1,2)的局势

(3)先手在“5”中取1个,后手就在 “3”和“5” 中各取走2个,这样成了(1,2)的局势

(4)先手在”5”中取2个,后手就在 “3”和”5”中各取走3个,这样变成了(0,0)的局势,先手输

(5)先手在“5”中取3个,后手就在 “3”和“5” 中各取走1个,也变成了(1,2)的局势

(6)先手在“5”中取4个,后手在“3”中取走1个,还是(1,2)的局势

我们可以来找找那些先手必输局势的规律(奇异局势)

  • 第一种(0,0)
  • 第二种(1,2)
  • 第三种(3,5)
  • 第四种  (4 ,7)
  • 第五种(6,10)
  • 第六种  (8,13)              
  • 第七种  (9 ,15)
  • 第八种  (11 ,18)
  • 第n种(a,b)

我们会发现他们的差值是递增的,分别是0,1,2,3,4,5,6,7……n

还有一个规律(正常人都发现不了):a=(b-a)*1.618向下取整

 就是:a = int(b – a)*1.618

注:这里的int是强制类型转换,注意这不是简单的四舍五入,假如后面的值是3.9,转换以后得到的不是4而是3,也就是说强制int类型转换得到的是不大于这个数值的最大整数

有些题目要求精度较高,我们可以用下述式子来表示这个值:

1.618 = (sqrt(5.0) + 1) / 2   

头文件:include<math.h>

例题:1067 — 取石子游戏 (poj.org)

题面:

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

 代码:

//#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll a,b;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(cin>>a>>b)//多组输入!!!
    {
        double flag= (sqrt(5.0) + 1) / 2.0;//精度高一些用double来存1.618
        if(a>b) swap(a,b);//保证b要比a大,后面有用到b-a
        if(a==int((b-a)*flag))cout<<0<<endl;//先手面对奇异局势必输
        else cout<<1<<endl;
    }

    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/181728.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • IDEA 2021.7.21 激活码【中文破解版】

    (IDEA 2021.7.21 激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月22日
    49
  • Spring MVC中redirect重定向3种方式(带参数)

    Spring MVC中redirect重定向3种方式(带参数)SpringMVC中做form表单功能提交时,防止用户客户端后退或者刷新时重复提交问题,需要在服务端进行重定向跳转,其中redirect是直接跳转到其他页面,有以下3种方法进行重定向。redirect重定向流程客户发送一个请求到服务器,服务器匹配servlet,这都和请求转发一样,servlet处理完之后调用了sendRedirect()这个方法,这个方法是response的方法,所以,……

    2022年10月22日
    0
  • EJB学习

    EJB学习EJB:企业级JavaBean(EnterpriseJavaBean, EJB)是一个用来构筑企业级应用的服务器端可被管理组件。EJB主要有三种Bean:SessionBeans:&

    2022年7月2日
    25
  • Pycharm设置解释器「建议收藏」

    Pycharm设置解释器「建议收藏」背景:最近需要改文章,增加实验,要把之前的实验跑起来。其间,遇到一个很诡异的问题,在一个工程里跑得很正常的程序,到了另外一个工程里,相似的文件,只是修改了一点参数而已,就会报错,如ModuleNotFoundError:Nomodulenamed’tensorflow.contrib.slim’,当时就怀疑是不是解释器设置问题。由于当时夜黑风高,困意来袭,解释器位置设置竟然也找不到,作罢。第二天直接复制粘贴找问题原因无果。问题:果然是解释器设置问题。默认的解释器是base的python环境,由.

    2022年8月25日
    3
  • SOP是什么?SOP的作用是什么?如何编写SOP?

    SOP是什么?SOP的作用是什么?如何编写SOP?SOP是由StandardOperationProcedure这三个英文单词的首个字母组合而成。也就是以统一化的标准将操作流程的步骤和要求罗列出来,用于指导和规范日常工作。SOP的核心,就是把特定流程的关键问题细化及量化。SOP是以文件的方式归纳总结操作人员在实际生产过程中的具体操作步骤和应当要注意的事项,它是车间现场操作人员的作业指导模板,也是质量检验人员用于检测指导工作的依据。SOP的作用:1、把企业长期累积的经验技术记录归纳,汇总成简单易懂的标准化文件,即使出现操作人员变动也不会使已有的技

    2022年5月9日
    56
  • 数据库优化分库分表_数据库分库分表的好处

    数据库优化分库分表_数据库分库分表的好处一.数据切分关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间。数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性

    2022年9月20日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号