首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

博弈论

编程知识
2024年07月24日 16:03

一、要素

  1. 局中人:在一场竞赛或博弈中,每一个有决策权的参与者成为一个局中人。只有两个局中人的博弈现象称为“两人博弈”,而多于两个局中人的博弈称为“多人博弈”。
  2. 策略:一局博弈中,每个局中人都有选择实际可行的完整的行动方案,即方案不是某阶段的行动方案,而是指导整个行动的一个方案,一个局中人的一个可行的自始至终全局筹划的一个行动方案,称为这个局中人的一个策略。如果在一局博弈中局中人都总共有有限个策略,则称为“有限博弈”,否则称为“无限博弈”。
  3. 得失:一局博弈结局时的结果称为得失。每个局中人在一局博弈结束时的得失,不仅与该局中人自身所选择的策略有关,而且与全局中人所取定的一组策略有关。
  4. 对于博弈参与者来说,存在着一博弈结果 。

摘自百度百科。

二、经典模型

从目录中跳转。

  • 巴什博弈(\(\mathcal{Bash\;game}\)

  • 威佐夫博弈(\(\mathcal{Wythoff's\;game}\)

  • 尼姆游戏(\(\mathcal{Nim\;Game}\)

  • SG 函数

A. 巴什博弈

双人博弈。

问题

有一堆总数为 \(n\) 的物品,\(2\) 名玩家轮流从中拿取物品。每次至少拿 \(1\) 件,至多拿 \(m\) 件,不能不拿,最终将物品拿完者获胜。

结论

\((m+1)\mid n\),则后手必胜,否则先手必胜。

注:这里的必胜以及下文的均表示有必胜策略。

简证

\(n=k(m+1)+d\),其中 \(k\in \mathcal{N}\)\(d\in \left[ \,0,m\,\right]\)

\(d= 0\) 时,设先手方拿走 \(x\) 个物品,则若后手每次拿取 \(m+1-x\) 个,那么每次后手行动后,剩余的物品数量仍然是 \(m+1\) 的倍数,直到最后一回合剩余 \(m+1\) 个,无论先手如何操作,最后总能剩下 \(\left[\,1,m\,\right]\) 个物品,后手获胜。

\(d\neq 0\) 时,由上定义可知,若先手方第一轮拿取 \(d\) 个,使得余下的数量为 \(m+1\) 的倍数,那么此时的先手就会成为 \(d=0\) 下的后手,按上述策略行动,则必获胜。

Code:

点击查看代码
namespace Bash
{
	short main()
	{
		int n,m;
		scanf("%d%d",&n,&m);
		if(n%(m+1)==0) printf("Player2 win.\n");
		else printf("Player1 win.\n");
		return 0;
	}
}

B. 威佐夫博弈

双人博弈。

问题

有两堆石子,两名玩家每次可以从任意一堆石子中取任意多的石子或者从两堆石子中取同样多的石子,最后取完者胜。

结论

枚举观察可以发现,在遇到特定的局势时,先手必败,我们称其为奇异局势。

在 OI 中应用较少。

判断奇异局势

证明见 百度百科

设当前局势为 \(\left(x,y\right)\),其中 \(x\lt y\),函数 \(\left[ x \right]\) 表示不超过 \(x\) 的最大整数,令 \(p=\frac{1+\sqrt{5}}{2}\),则形如 \(\left( \left[ k\times p\right],\left[k\times p^2\right]\right)\) 的局势一定为奇异局势。

转换成判断形式为 \(\left(y-x\right)\times p = x\),满足即为奇异局势。

Code:

P2252

这道题卡精度,需要手写 sqrt 并且调用 std 库才可 AC。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
namespace Wythoff
{
	long double Wsqrt(long double n)
	{
		long double s=sqrt(n);
		for(int i=1;i<=n;i++) s=n/s;
		return s;
	}
	short main()
	{
		long long x,y,z;
		scanf("%lld%lld",&x,&y);
		z=abs(x-y)*((Wsqrt(5)+1)/2.0L);
		if(z==min(x,y)) printf("0\n");
		else printf("1\n");
		return 0;
	}
}
int main(){return Wythoff::main();}

C. 尼姆游戏

双人博弈。

问题

有若干堆石子,每堆石子的数量都是有限的,合法的移动是选择一堆石子并拿走若干大于零颗,最后取完者胜。

结论

设一种局势的状态为 \(\left(a_1,a_2,\ldots,a_n\right)\),则若 \(a_1\oplus a_2\oplus \ldots \oplus a_n=0\),则后手必胜,否则先手必胜。

简证

定义 P-position(Previous) 为后手必胜局势,简称 P 状态;N-position(Next) 为先手必胜局势,简称 N 状态。

我们将每一种状态视为一个节点,并将其向其后继状态连边,这样就得到了一个博弈状态图。

那么显然的是,入度为 \(0\) 的点为初始状态,出度为 \(0\) 的点为最终游戏结束时的状态,并且为 P 局势(在结束时的状态先手的人显然无法有任何操作)。

那么通过推理,我们还可以得到两条定理:

  1. 一个状态为 N 状态当且仅当存在至少一个 P 状态为它的后继状态。

  2. 一个状态是 P 状态当且仅当它的所有后继状态均为 N 状态。

解释一下。

对于定理 1,若该状态存在至少一个 P 状态,那么玩家可通过操作到达该状态,使对手进入 P 状态,进而自己必胜。

对于定理 2,若该状态的所有后继状态都为 N 状态,即无论如何操作都会使对手进入 N 状态,进而自己必败。

若该博弈状态图是一个有向无环图,那么根据这些已知定理,我们可以用 \(\mathcal{O}(N+M)\) 的时间得出每个状态是 P 状态还是 N 状态。

但是复杂度太高,于是我们考虑结论中 \(\mathcal{O(1)}\) 的判断方法。我们先设 \(k=a_1\oplus a_2 \oplus\ldots\oplus a_n\)

若想得到该结论,只需证明一下两个定理:

  1. 对于 \(k \neq 0\) 的状态,存在至少一种后继状态使得 \(k =0\)

  2. 对于 \(k=0\) 的状态,所有的后继状态的 \(k\) 值均不为 \(0\)

image

来自 OI-wiki。

Code:

P2197

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T;cin>>T;
    while(T--)
    {
        int n,ans=0;cin>>n;
        for(int i=1;i<=n;i++)
        {
            int a;cin>>a;ans^=a;
        }
        if(ans==0) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}

应用——SG 函数

引入

  • \(\mathcal{Sprague–Grundy}\) 定理

定义 mex 函数为不属于集合 S 中的最小自然数,即 \(mex(S)=min\{ x \} \left(x\notin S,x\in N\right)\)

对于一个状态 x 和它的所有后继状态 \(y_1,y_2,\ldots , y_n\),定义 SG 函数为:

\[SG(x)=mex\{SG(y_1),SG(y_2),\ldots,SG(y_n)\} \]

对于由 \(n\) 个有向图游戏组成的组合游戏,设它们的起点分别为 \(s_1,s_2,\ldots,s_n\),那么当且仅当 \(SG(s_1)\oplus SG(s_2)\oplus\ldots\oplus SG(s_n)\neq 0\) 时,先手必胜。这就是 SG 定理。

  • 一个游戏的 SG 函数
    讲一个游戏 \(X\) 拆分成若干个子游戏 \(s_1,s_2,\ldots,s_n\),那么该游戏的 SG 函数值为:

\[SG(X)=SG(s_1)\oplus SG(s_2)\oplus \ldots\oplus SG(s_n) \]

简证

image

摘自 OI-wiki。

三、例题

A. Game On Tree

AGC017D

很基础的 SG 函数应用题,只需要求出整棵树的 SG 值即可。

但真的只是用求所有子树的 SG 值异或和吗?

仔细观察,这道题其实可以转化为树上的关于边的尼姆游戏,每一棵子树到根还有一条未被算入的边,因此正确的结果应该为:

\[SG(X)=(SG(a_1)+1)\oplus (SG(a_2)+1)\oplus\ldots\oplus (SG(a_n)+1) \]

Code:

点击查看代码
#include<bits/stdc++.h>

const int Ratio=0;
const int N=2e5+5;
int n,m;
int hh[N],ne[N<<1],to[N<<1],cnt;

namespace Wisadel
{
    void Wadd(int u,int v)
    {
        to[++cnt]=v;
        ne[cnt]=hh[u];
        hh[u]=cnt;
    }
    int Wdfs(int u,int fa)
    {
        int sum=0;
        for(int i=hh[u];i!=-1;i=ne[i])
            if(to[i]!=fa) sum^=Wdfs(to[i],u)+1;
        return sum;
    }
    short main()
    {
        memset(hh,-1,sizeof hh);
        scanf("%d",&n);cnt=0;

        for(int i=1,a,b;i<n;i++)
            scanf("%d%d",&a,&b),
            Wadd(a,b),Wadd(b,a);

        if(Wdfs(1,0)) printf("Alice\n");
        else printf("Bob\n");
        return Ratio;
    }
}
int main(){return Wisadel::main();}

B. Alice 和 Bob 又在玩游戏

P6665

可以显然看出这是一个用 SG 函数求解的问题,显然我们只需对每个连通块计算一遍其 SG 值异或起来检验是否非零即可。

这道题删的边是与根节点联通的边,也就是删边操作后会形成森林,这些森林也就是每个状态的后继。我们发现,不同的树之间的操作互不影响,将它们看做不同的游戏,那么该后继状态的 SG 值其实就是每一个游戏的 SG 值的异或和。

根据 SG 定理,我们的任务转化成了快速求出所有树的 SG 值的mex 值。

考虑用 0-1trie 维护,可以达到 \(\mathcal{O(n\,logn)}\) 的复杂度。


完结撒花~

From:https://www.cnblogs.com/Ratio-Yinyue1007/p/18317441
本文地址: http://shuzixingkong.net/article/380
0评论
提交 加载更多评论
其他文章 RestSharp编写api接口测试,并实现异步调用(不卡顿)
首先,确保你已经安装了RestSharp NuGet包。如果没有安装,可以通过以下命令安装: bash Install-Package RestSharp 然后,在你的C#代码中,你可以按照以下步骤操作: 引用RestSharp命名空间。 创建一个RestClient实例。 创建一个RestRequ
DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)
DASCTF 2023 &amp; 0X401七月暑期挑战赛【PWN】(FileEditor篇) 题目保护情况(保护全家桶) 64位ida逆向 模拟了一个类似vim的功能,有打开文件,打印内容,插入行,删除行,复制行,和编辑行,还有查找字符和替换字符的功能,然后就是保存退出 一个一个来分析吧 1.o
DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇) DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇) DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)
Android Spingboot 实现SSE通信案例
SSE SSE(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。 Server-Sent Events (SSE) 和 Socke
Android Spingboot 实现SSE通信案例 Android Spingboot 实现SSE通信案例 Android Spingboot 实现SSE通信案例
Known框架实战演练——进销存业务单据
本文介绍如何实现进销存管理系统的业务单据模块,业务单据模块包括采购进货单、采购退货单、销售出货单、销售退货单4个菜单页面。由于进销单据字段大同小异,因此设计共用一个页面组件类。 项目代码:JxcLite 开源地址: https://gitee.com/known/JxcLite 1. 配置模块 运行
2个月搞定计算机二级C语言——真题(1)解析
1. 前言 大家好,我是梁国庆。 这段时间将持续发布计算机二级 C 语言真题的解析,想要同步练习,需要资源包的朋友可以跳转免费获取——《3个月搞定计算机二级C语言——准备工作》。 现在恐怕要改为 2 个月搞定计算机二级 C 语言了,不过没有关系,干就完了! 本篇博客将解析计算机二级 C 语言考试真题
2个月搞定计算机二级C语言——真题(1)解析 2个月搞定计算机二级C语言——真题(1)解析 2个月搞定计算机二级C语言——真题(1)解析
AI知识库这事儿FastGPT是专业的
在搭建AI知识库这事儿上,有不少成熟的框架,我推荐使用FastGPT。这篇文章笔者就使用过的两款平台做个比较,FastGPT和百度千帆平台。
AI知识库这事儿FastGPT是专业的 AI知识库这事儿FastGPT是专业的 AI知识库这事儿FastGPT是专业的
Centos7下安装配置最新版本Jenkins(2.452.3)
1、基础环境配置 1.1 服务器下载Jenkins安装包 下载地址:https://www.jenkins.io/download/ 下载命令:wget https://get.jenkins.io/war-stable/2.452.3/jenkins.war 1.2 服务器安装配置JDK Jenk
Centos7下安装配置最新版本Jenkins(2.452.3) Centos7下安装配置最新版本Jenkins(2.452.3) Centos7下安装配置最新版本Jenkins(2.452.3)
Nacos 高级详解:提升你的开发和部署效率
Nacos 高级 一 、服务集群 需求 服务提供者搭建集群 服务调用者,依次显示集群中各服务的信息 搭建 修改服务提供方的controller,打印服务端端口号 package com.czxy.controller; import org.springframework.web.bind.anno
Nacos 高级详解:提升你的开发和部署效率 Nacos 高级详解:提升你的开发和部署效率 Nacos 高级详解:提升你的开发和部署效率