各种博弈论详解

目录

  • 博弈论

    • 1.公平组合博弈(ICG)

      • SG定理:
      • SG函数性质:
      • SG函数求法
    • 2.Bash(巴什博弈)
    • 3.Nim博弈(尼姆博弈)
    • 4.Wythoff Game(威佐夫博弈)
    • 5.Fibonacci博弈

博弈论

理论铺垫:

定义P-positionN-position:其中P代表Previous,N代表Next。直观的说,上一次move的人有必胜策略的局面是P-position,即P-position代表先手必输,N-position代表先手必赢。

1.公平组合博弈(ICG)

定义:

1.两个人轮流参与; 2.游戏局面有限; 3.同一个局面两个人操作完全相同; 4.无法进行操作的人输; 5.在有限步内结束。

模型:给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负。

解题思路:SG函数(Sprague-Grudy)

SG定理:

1:给定一个有限子集 S ? N,令mex S为没有出现在S中的最小自然数。例:mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

2:对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:sg(x)=mex{ sg(y) | y是x的后继 }。即y可以一步操作到x;

SG函数性质:

1:SG值为0必败态, 否则为必胜态

2:对于一个sg(x)=0的顶点x,它的所有后继y都满足g(y)!=0。同理,对于一个sg(x)!=0的顶点,必定存在一个后继y满足g(y)=0。

例:有三堆石子,第一堆石子的可以取1、2、3个石子,则:sg[x] = x % 4;第二堆可以取奇数个石子,则sg[x] = n % 2;第三堆有n个石子,其为Nim博弈,sg值为n,将三堆的sg值全部异或一下,判断是不是0,是0则先手必败(推广到n堆其结论一样适用)。

SG函数求法

其sg函数可以通过下面的模板来求:

//f[]:可以取走的石子个数
//sg[]:0~n的SG函数值
//hash[]:mex{}
int f[N],sg[N],hash[N];
void getSG(int n)
{
    int i,j;
    memset(sg,0,sizeof(sg));
    for(i=1;i<=n;i++)
    {
        memset(hash,0,sizeof(hash));
        for(j=1;f[j]<=i;j++)
            hash[sg[i-f[j]]]=1;
        for(j=0;j<=n;j++)    //求mes{}中未出现的最小的非负整数
        {
            if(hash[j]==0)
            {
                sg[i]=j;
                break;
            }
        }
    }
}

记忆化搜索求SG函数,判断该点的sg值是否为-1,如果是,则调用函数:

//注意 S数组要按从小到大排序 SG函数要初始化为-1 对于每个集合只需初始化1遍
//n是集合s的大小 f[i]是定义的特殊取法规则的数组
int s[110],sg[10010],n;
void SG_dfs(int x)
{
    int i;
    if(sg[x]!=-1)
        return;
    bool vis[maxn];
    memset(vis,0,sizeof(vis));
    for(i=1;i<=k;i++)
    {
        if(x>=f[i])
        {
            if(sg[x-f[i]]==-1)
                SG_dfs(x-f[i]);
            vis[sg[x-f[i]]]=1;
        }
    }
    int e;
    for(i=0;;i++)
        if(!vis[i])
        {
            sg[x]=i;
            break;
        }
}

AC代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn=1e4+5;
int f[101],sg[maxn];
int k,T,tot=0,temp,inf;
void SG_dfs(int x)
{
    int i;
    if(sg[x]!=-1)
        return;
    bool vis[maxn];
    memset(vis,0,sizeof(vis));
    for(i=1;i<=k;i++)
    {
        if(x>=f[i])
        {
            if(sg[x-f[i]]==-1)
                SG_dfs(x-f[i]);
            vis[sg[x-f[i]]]=1;
        }
    }
    int e;
    for(i=0;;i++)
        if(!vis[i])
        {
            sg[x]=i;
            break;
        }
}

int main()
{
    //ios::sync_with_stdio(false);
    while(scanf("%d",&k)&&k)
    {
        //memset(f,0,sizeof(f));
        memset(sg,-1,sizeof(sg));
        sg[0]=0;
        for(int i=1;i<=k;++i){
            scanf("%d",&f[i]);
        }
        //sort(f+1,f+k+1);
        scanf("%d",&T);
        while(T--)
        {
            tot=0;
            scanf("%d",&temp);
            for(int i=1;i<=temp;++i){
                scanf("%d",&inf);
                if(sg[inf]==-1)
                    SG_dfs(inf);
                tot^=sg[inf];
            }
            !tot?cout<<"L":cout<<"W";
        }
        cout<<endl;
    }
    system("pause");
    return 0;
}

2.Bash(巴什博弈)

定义:有一堆共n个物品,两个人轮流从中间取,每次最多取m个物品,先取完的人赢。

解题思路:n对(m+1)取模,模不为0,则先手必胜,模为0,则先手必败(由SG函数知)。

3.Nim博弈(尼姆博弈)

定义:有n堆物品,两人轮流从每堆中取物品,每次最少取一个,无上限,先取完者胜利。

解题思路:所有堆的个数相异或,如果结果为0,则先手必败,不为0则先手必胜。必胜走法的方案数:将总的异或结果同每一堆相异或,如果结果小于该堆的数量,则可以从该堆取出x-x^tot个;

4.Wythoff Game(威佐夫博弈)

定义:有两堆若干个物品,两人轮流从一堆中取若干的物品或两堆取同样多的额物品,至少取一个,先取完的为胜。

解题思路:令当前局势(Ak,Bk),则当前态势为先手必败态当且仅当Ak=((sqrt(5)+1)/2)*k、Bk=Ak+k;取出多少个则直接暴力循环判断是不是必败态即可

5.Fibonacci博弈

定义:有一堆个数为n的石子,双方轮流取石子,先手不能一次把所有石头取完,且后者取得石子的数目不能超过前者所取数目的2倍(可以包含1和2倍)。

解题思路:判断该数是不是裴波那契数列,如果是,则先手必败,否则先手必胜。

原文地址:https://www.cnblogs.com/StungYep/p/12254195.html

时间: 2024-10-12 21:41:06

各种博弈论详解的相关文章

【基础操作】博弈论详解

博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子) 先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 模板题(Nim 游戏) 有 $n$ 堆石子,两个人轮流从任意一堆石子中取出正整数个石子,取不了的一方输.问先手是否有必胜策略. 题解 经典的博弈论模板题. 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/game_theory.html

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

转载:DenseNet算法详解

原文连接:http://blog.csdn.net/u014380165/article/details/75142664 参考连接:http://blog.csdn.net/u012938704/article/details/53468483 本文这里仅当学习笔记使用,具体细节建议前往原文细度. 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github链接:h

MariaDB(MySQL)创建、删除、选择及数据类型使用详解

一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品.在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB. MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL A

HttpServletResponse和HttpServletRequest详解

HttpServletResponse,HttpServletRequest详解 1.相关的接口 HttpServletRequest HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletRequest接口可以获取由客户端传送的名称,也可以获取产生请求并且接收请求的服务器端主机名及IP地址,还可以获取客户端正在使用的通信协议等信息.下表是接口HttpServletRequest的常用方法. 说明:HttpServ

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)

阅读目录: 1.环路执行对象模型.碎片化执行模型(假递归式调用) 2.N层对象执行模型(纵横向对比链式扩展方法) 3.LINQ查询表达式和链式查询方法其实都是空壳子 4.详细的对象结构图(对象的执行原理) 5.IQueryable<T>与IQueryProvider一对一的关系能否改成一对多的关系 6.完整的自定义查询 1]. 环路执行对象模型.碎片化执行模型(假递归式调用) 这个主题扯的可能有点远,但是它关系着整个LINQ框架的设计结构,至少在我还没有搞懂LINQ的本意之前,在我脑海里一直频

netstat状态详解

一.生产服务器netstat tcp连接状态................................................................................ 2 1.1生产服务器某个业务LVS负载均衡上连接状态数量............................................... 2 1.2生产服务器某个业务web上连接状态数量...............................................

详解go语言的array和slice 【二】

上一篇  详解go语言的array和slice [一]已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变.这一篇里我会讲解到如何避免这些问题,以及迭代.和做为方法参数方面的知识点. slice的长度和容量设置为同一个值 如果在创建新的slice时我们把