2.6-组合博弈入门
组合博弈入门
组合游戏
要求
- 有两个玩家;
- 游戏的操作状态是一个有限的集合(比如:限定大小的棋盘);
- 游戏双方轮流操作;
- 双方的每次操作必须符合游戏规定;
- 当一方不能将游戏继续进行的时候,游戏结束,同时,对方为获胜方;
- 无论如何操作,游戏总能在有限次操作后结束。
必败点和必胜点(P点&N点)
必败点(P点):上一个选手(Previous player)将取胜的位置成为必败点。
必胜点(N点):下一个选手(Next player)将取胜的位置成为必胜点。
必败(必胜)点属性
-
所有终结点是必败点(P点);
-
从任何必胜点(N点)操作, 至少有一种方法可以进入必败点(P点);
-
无论如何操作,从必败点(P点)都只能进入必败点(P点)。
取子游戏的算法实现
步骤1:将所有终结位置标记为必败点(P点);
步骤2:将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)
步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点),则将该点标记为必败点(P点);
步骤4:如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。
NIM游戏
NIM游戏是组合博弈中的经典游戏。游戏场景如下:有若干堆石子,每堆石子的数量都是有限的,游戏双方轮流从某一堆中取走任意数量的石子(至少取1个),取走最后一个石子的玩家获胜。
NIM游戏的二进制证明
设游戏中有 n n n 堆石子,各堆石子数分别为 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots,a_n a1,a2,⋯,an。将这些石子数都表示成二进制形式。
定义NIM - 和为 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n a_1\oplus a_2\oplus\cdots\oplus a_n a1⊕a2⊕⋯⊕an( ⊕ \oplus ⊕ 表示按位异或运算)。
-
定理:NIM游戏中,当且仅当 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = 0 a_1\oplus a_2\oplus\cdots\oplus a_n = 0 a1⊕a2⊕⋯⊕an=0 时,当前局面为必败局面;当 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n ≠ 0 a_1\oplus a_2\oplus\cdots\oplus a_n\neq0 a1⊕a2⊕⋯⊕an=0 时,当前局面为必胜局面。
-
证明
-
终结局面:当所有堆石子数都为 0 0 0 时, 0 ⊕ 0 ⊕ ⋯ ⊕ 0 = 0 0\oplus0\oplus\cdots\oplus0 = 0 0⊕0⊕⋯⊕0=0,此时是必败局面。
-
必胜局面可转化为必败局面:若 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = k ≠ 0 a_1\oplus a_2\oplus\cdots\oplus a_n = k\neq0 a1⊕a2⊕⋯⊕an=k=0,则 k k k 的二进制表示中至少有一位为 1 1 1。在 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots,a_n a1,a2,⋯,an 中一定存在一个 a i a_i ai,其对应的二进制位上也为 1 1 1。通过从第 i i i 堆中取走一定数量的石子,使得取走后这堆石子数变为 a i ′ a_i' ai′,满足 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a i − 1 ⊕ a i ′ ⊕ a i + 1 ⊕ ⋯ ⊕ a n = 0 a_1\oplus a_2\oplus\cdots\oplus a_{i - 1}\oplus a_i'\oplus a_{i+1}\oplus\cdots\oplus a_n=0 a1⊕a2⊕⋯⊕ai−1⊕ai′⊕ai+1⊕⋯⊕an=0。
-
必败局面只能转化为必胜局面:若 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = 0 a_1\oplus a_2\oplus\cdots\oplus a_n = 0 a1⊕a2⊕⋯⊕an=0,假设从第 i i i 堆取走石子后变为 a i ′ a_i' ai′,那么 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a i − 1 ⊕ a i ′ ⊕ a i + 1 ⊕ ⋯ ⊕ a n ≠ 0 a_1\oplus a_2\oplus\cdots\oplus a_{i - 1}\oplus a_i'\oplus a_{i+1}\oplus\cdots\oplus a_n\neq0 a1⊕a2⊕⋯⊕ai−1⊕ai′⊕ai+1⊕⋯⊕an=0。因为异或运算的性质决定了,改变其中一个数后,异或和必然改变。
-
SG函数
对于一个组合游戏的每个状态 x x x,定义其SG函数值 S G ( x ) SG(x) SG(x)。
-
计算方法:
-
首先,对于所有的终结状态 x x x, S G ( x ) = 0 SG(x)=0 SG(x)=0。
-
对于非终结状态 x x x,设 x x x 能通过一步操作到达的所有状态为 y 1 , y 2 , ⋯ , y k y_1,y_2,\cdots,y_k y1,y2,⋯,yk,则 S G ( x ) = m e x ( { S G ( y 1 ) , S G ( y 2 ) , ⋯ , S G ( y k ) } ) SG(x)=mex(\{SG(y_1),SG(y_2),\cdots,SG(y_k)\}) SG(x)=mex({SG(y1),SG(y2),⋯,SG(yk)}),其中 m e x mex mex 函数是求一个集合中未出现的最小非负整数。例如,若集合为 { 0 , 1 , 3 } \{0,1,3\} {0,1,3},则 m e x ( { 0 , 1 , 3 } ) = 2 mex(\{0,1,3\}) = 2 mex({0,1,3})=2。
-
-
作用:
- 当一个组合游戏可以拆分为多个子游戏时,整个游戏的胜负情况可以通过各个子游戏的SG函数值的异或和来判断。设整个游戏由 n n n 个子游戏组成,每个子游戏的当前状态对应的SG函数值分别为 S G 1 , S G 2 , ⋯ , S G n SG_1,SG_2,\cdots,SG_n SG1,SG2,⋯,SGn,则当 S G 1 ⊕ S G 2 ⊕ ⋯ ⊕ S G n = 0 SG_1\oplus SG_2\oplus\cdots\oplus SG_n = 0 SG1⊕SG2⊕⋯⊕SGn=0 时,当前游戏局面为必败局面;当 S G 1 ⊕ S G 2 ⊕ ⋯ ⊕ S G n ≠ 0 SG_1\oplus SG_2\oplus\cdots\oplus SG_n\neq0 SG1⊕SG2⊕⋯⊕SGn=0 时,当前游戏局面为必胜局面。这使得我们可以将复杂的组合游戏分解为简单子游戏来分析胜负情况。
组合游戏的并
定义:组合游戏的并是指将多个组合游戏同时进行的一种游戏形式。假设有 k k k 个组合游戏 G 1 , G 2 , ⋯ , G k G_1, G_2, \cdots, G_k G1,G2,⋯,Gk,组合游戏的并 G = G 1 + G 2 + ⋯ + G k G = G_1 + G_2 + \cdots + G_k G=G1+G2+⋯+Gk。在游戏 G G G 中,玩家的一步操作是在 G 1 , G 2 , ⋯ , G k G_1, G_2, \cdots, G_k G1,G2,⋯,Gk 中的某一个游戏中进行一步合法操作。
SG 定理:对于组合游戏的并 G = G 1 + G 2 + ⋯ + G k G = G_1 + G_2 + \cdots + G_k G=G1+G2+⋯+Gk,其某状态的 S G SG SG 值等于各个子游戏在相应状态下 S G SG SG 值的异或和,即 S G ( G ) = S G ( G 1 ) ⊕ S G ( G 2 ) ⊕ ⋯ ⊕ S G ( G k ) SG(G)=SG(G_1)\oplus SG(G_2)\oplus\cdots\oplus SG(G_k) SG(G)=SG(G1)⊕SG(G2)⊕⋯⊕SG(Gk)。这个定理非常重要,它使得我们可以通过分别计算各个子游戏的 S G SG SG 值,再求异或和来判断组合游戏并的胜负情况。
以下是一个简单示例代码,展示如何利用 SG 定理计算组合游戏的并的胜负情况(假设已有 sg 函数用于计算单个游戏状态的 S G SG SG 值)
#include<bits/stdc++.h>using namespace std;// 假设已经有了计算单个游戏 SG 值的函数 sgint sg(int state) {// 具体实现省略,根据实际游戏规则编写return 0; }计算组合游戏的并的 SG 值int combinedSG(int numGames, int* states) {int result = 0;for (int i = 0; i < numGames; ++i) {result ^= sg(states[i]);}return result;}// 判断胜负示例函数void determineWinner(int numGames, int* states) {int combinedSgValue = combinedSG(numGames, states);if (combinedSgValue == 0) {cout << "当前局面为必败局面" << endl;}else {cout << "当前局面为必胜局面" << endl;}}int main() {int numGames = 3; // 假设有 3 个子游戏int states[3] = {1, 2, 3}; // 各个子游戏的状态determineWinner(numGames, states);return 0;}
相关文章:
2.6-组合博弈入门
组合博弈入门 组合游戏 要求 有两个玩家;游戏的操作状态是一个有限的集合(比如:限定大小的棋盘);游戏双方轮流操作;双方的每次操作必须符合游戏规定;当一方不能将游戏继续进行的时候…...

【教学】推送docker仓库
引言 Docker Hub 这个最常见的公共 Docker 仓库为例,本文将介绍如何把本地 Docker 镜像推送到公共 Docker 仓库 1. 注册 Docker Hub 账号 如果你还没有 Docker Hub 账号,需要先在 Docker Hub 官网 进行注册。注册完成后,记住你的用户名和密…...

【大数据技术】本机PyCharm远程连接虚拟机Python
本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …...

3060显卡掉帧是为什么?3060掉帧卡顿解决方法
NVIDIA GeForce RTX 3060是一款性能强劲的显卡,它可以在高画质的情况下运行大多数的游戏,但是也有一些用户反映,3060玩游戏时会出现掉帧和卡顿的现象,这让很多玩家感到困扰。那么,3060显卡掉帧是什么原因呢?…...
Kubernetes集群通过Filebeat收集日志
Filebeat收集容器日志,其中NODE_NAME配置,是将node信息添加到日志中,所以需要serviceAccount权限,如果不需要配置NODE信息,可以不创建serviceAccount,其他内容可根据实际情况修改 apiVersion: v1 kind: Ser…...

SQLAlchemy-2.0中模型定义和alembic的数据库迁移工具
SQLAlchemy-2.0中模型定义和alembic的数据库迁移工具 一、SQLAIchemy的介绍二、数据库引擎1、支持的数据库1.1、sqlite数据库1.2、MySQL数据库1.3、数据库引擎的参数 三、定义模型类1、定义模型2、engine负责数据库迁移 四、alembic数据库迁移⼯具1、安装alembic2、初始化alemb…...

[含文档+PPT+源码等]精品基于Python实现的django个性化健康餐计划订制系统
软件开发环境及开发工具: 开发语言:python 使用框架:Django 前端技术:JavaScript、VUE.js(2.X)、css3 开发工具:pycharm、Visual Studio Code、HbuildX 数据库:MySQL 5.7.26&am…...
Python3中异常处理:try/except语句
一. 简介 什么是异常处理 ? 在 Python中,异常处理是一种用于管理程序运行时错误的机制。通过使用异常处理,你可以编写更加健壮和可靠的代码。 Python 提供了 try,except,else和 finally关键字来处理异常,…...
[ Spring] Integrate Spring Boot Dubbo with Nacos 2025
文章目录 Dubbo Project StructureDeclare Plugins and RepositoriesIntroduce DependenciesDubbo Consumer PropertiesDubbo Provider ApplicationDubbo Provider ServiceDubbo Consumer PropertiesDubbo Consumer ApplicationDubbo Consumer ControllerCommand References Du…...

【3分钟极速部署】在本地快速部署deepseek
第一步,找到网站,下载: 首先找到Ollama , 根据自己的电脑下载对应的版本 。 我个人用的是Windows 我就先尝试用Windows版本了 ,文件不是很大,下载也比较的快 第二部就是安装了 : 安装完成后提示…...

【QT笔记】使用QScrollArea实现多行文本样式显示
目录 一、QScrollArea 的基本概念 二、demo代码 三、实现效果 1、页面空间足够,无滚动条时显示效果 2、有滚动条时显示效果 一、QScrollArea 的基本概念 QScrollArea 是 Qt 框架中用于提供一个滚动条区域,允许用户滚动查看比当前可视区域更大的内容…...

大模型中提到的超参数是什么
在大模型中提到的超参数是指在模型训练之前需要手动设置的参数,这些参数决定了模型的训练过程和最终性能。超参数与模型内部通过训练获得的参数(如权重和偏置)不同,它们通常不会通过训练自动学习,而是需要开发者根据任…...

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据
一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址: https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动,会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…...

UE虚幻引擎No Google Play Store Key:No OBB found报错如何处理
UE虚幻引擎No Google Play Store Key:No OBB found报错如何处理? 问题描述: UE成功打包APK并安装过后,启动应用时提示: No Google Play Store KeyNo OBB found and no store key to try to download. Please setone …...
OKHttp拦截器解析
OKHttp涉及到拦截器大概的执行步骤为: 1.通过newCall生成RealCall对象 具体代码如下: Override public Call newCall(Request request) {return new RealCall(this, request, false /* for web socket */);}2.调用Call的execute方法 当然这也可以是执…...

STM32标准库移植RT-Thread nano
STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接:STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码(最好带有点灯和串口)RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生,正在学习阶段&a…...
c++11总结26——std::regex
std::regex 是 C11 引入的 正则表达式库,用于 字符串匹配、搜索和替换。 🔹 头文件:#include <regex> 🔹 命名空间:std 🔹 支持的匹配模式:ECMAScript(默认)、POS…...

langchain教程-12.Agent/工具定义/Agent调用工具/Agentic RAG
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...
leetcode_双指针 125.验证回文串
125.验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s,如果它是回文串 ,返回 true ÿ…...
ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练
文章目录 (文末提供数据集下载)ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练目标项目概述代码结构概述1. **主要类和文件**2. **命名空间和使用指令**3. **数据类 (TransactionObservation)**4. **主程序入口 (Main 方法)**5. **数据预处理 (DataPrepr…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...