博弈论学习笔记(一):博弈论基础知识、常见博弈类型

基本概念

博弈定义:在一定条件下,遵守一定的规则,一个或几个拥有绝对理性思维的人或团队,从各自允许选择的行为或策略进行选择并加以实施,并从中各自取得相应结果或收益的过程。

举几个例子来说说什么是博弈:

  • 经济学:股市是按照这样的方式运行的:每个人可以持有股票,如果抛出过多股票则股价下跌,没有抛股票的人血亏。因此当金融危机发生时,如果有某些消息让一部分股民抛售了股票,剩下的人也必须跟着抛售,抛售越晚越亏。

  • 买卖交易:一般买东西的时候,由商家先给出一个价格,随后顾客将这个价格压低,随后商家再
    将这个压低的价格抬高,重复过程。顾客会希望最小化最终价格,而商家会希望最大化。

  • 小学数学:桌子上有 20 个硬币。Alice 和 Bob 两个人依次取硬币,每次可以取一枚或两枚,Alice 先开始取。取到最后一枚硬币的人获胜。问谁会获胜。


一些定义:

  • Game theory:传统意义上的博弈论,涉及经济学,逻辑学,计算机科学等。

  • Combinatorial game theory:Game theory 的一部分,主打的是 “sequential gameswith perfect information”。“sequential” 指的是双方交替行动, 而非同时行动,“perfect information” 指的是双方在做决策的时候都知道当前局面处于什么状态,以
    及可以向什么状态转移。

  • Complete information game theory:指的是博弈双方都清楚双方的目标(或者采取某些操作对双方的收益)。当然 OI 范围内的一般都是完全信息博弈。

  • impartial game:在博弈的同一状态下,如果不论是谁做操作,可能做出的决策集合是相同的, 那么就是一个平等博弈。平等博弈意味着我们不用区分一个状态下是 “Alice 做操作” 还是 “Bob 做操作”,因此只要博弈可以终止,递归可证一个局面要么是 “先手必胜” 的,要么是 “后手必胜”的。

象棋/围棋:perfect & complete。

扑克牌:imperfect & complete。你在打牌的时候是不知道对手的手牌的,也即不知道现在是处于博弈的哪个状态的。

狼人杀/三国杀:imperfect & incomplete,此时不仅你不知道对手有哪些可能的决策,甚至不知道对手的身份,也就对应不知道对手的获胜目标。

这三者都不是平等博弈。


OI 比赛中常见的博弈有如下的几种类型:

  • 传统组合数学意义上的经典模型,如 Nim 博弈,Nash 博弈等。

  • 没什么经典模型,但是比较考验选手对整个博弈的细致分析的,比如仔细考虑博弈双方的最优策略等。

  • 完全是套了一个博弈的壳,其实是在考察其它内容,比如组合数学/图论等。

经典模型

有向图博弈(Game on DAG)

有一张有向无环图,其中一个节点上有一个棋子。从 Alice 开始游戏,Alice 和 Bob 轮流将这个棋子沿着一条有向出边移动,无法移动者判负。问最后谁会获胜。

解:注意到这是一个平等博弈,那么我们可以从无法移动的点回推,就可以判断到这个点时是先手必胜还是后手必胜。

Ferguson Game

有两堆石子分别 n,m 个。双人博弈,每次操作是清空其中一堆石子并将另一堆石子分成非空的两堆新的石子。 无法操作者输。问最后谁会获胜。

解:平等博弈。我们将先手必胜状态设为 N,先手必败状态设为 P (下同),先打表找规律:

m\n 1 2 3 4
1 P N P N
2 N N N N
3 P N P N
4 N N N N

猜想:两堆石子均为奇数则先手必败,否则先手必胜。

证:考虑数学归纳法。

对于 m=1n=1 的情况,先手必败(P),猜想成立。

max(n,m)=2 时,根据打表结果,对于 n=2,m=1n=1,m=2n=2,m=2 的情况,先手必胜(N),猜想成立。

假设猜想对于 max(n,m)<k 时成立,现在证明对于 max(n,m)=k 时猜想也成立。

n,m 中有一偶数,假设是 n,则先手可以将另外那堆石子清空,将 n 划分成两个奇数 a,b,发现 a,b<nk,且此时先后手交换,根据假设,此时是先手必败状态(P),也就是操作前的先手必胜状态(N)

n,m 都是奇数,则先手将一堆石子清空,将 n 划分成一个奇数 a 和一个偶数 b,发现 a,b<nk,且此时先后手交换,根据假设,此时是先手必胜状态(N),也就是操作前的先手必败状态(P)

符合数学归纳法,猜想成立。

Chomp Game

有一块 n×m 的网格。双人博弈,每次操作是选中其中一个未被删除的格子 (x0,y0),将所有 xx0yy0 的格子 (x,y) 删除。删除 (1,1) 的人输。问最后谁会获胜。

解:平等博弈。先打表找规律。

m\n 1 2 3 4
1 P N N N
2 N N N N
3 N N N N
4 N N N N

猜想:只要 n1m1,那么这个游戏一定先手获胜。

证:考虑反证法。

假设先手必败,无论先手怎么取,后手都能获胜。假设先手取 (n,m),后手会通过某种取法进入必胜状态,考虑到任何一种取法都会取到 (n,m),那么先手可以先采用后手的必胜策略进入必胜状态,这与一开始的假设错误,因此假设不成立。

猜想成立。

Bash Game

有一堆石子共 n 个。双人博弈,每次从石子堆中取出 1m 个石子。无法操作者输。问最后谁会获胜。

解:平等博弈。先打表找规律。

m\n 1 2 3 4 5
1 N P N P N
2
3
4
5

SG函数与SG定理

例题

Nim Game

洛谷 P2197 【模板】Nim 游戏

完整代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e4 + 9;
int a[N], T, n;
signed main(){
	scanf("%lld", &T);
	while(T--){
		scanf("%lld", &n);
		for(int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		int ans = a[1];
		for(int i = 2; i <= n; i++)
			ans ^= a[i];
		if(!ans)
			printf("No\n");
		else
			printf("Yes\n");
	}
	return 0;
} 

Lasker's Nim Game

现在有 n 堆石子,第 i 堆有 ai 个。双人博弈,每次从一个当前非空的石子堆当中取至少一个,或者选取一个石子堆分成两个非空的石子堆。无法操作者输。问最后谁会获胜。

n105,ai109

Anti-Nim Game

Nim 游戏,但是变为不能取石子的人获胜。

n105,ai109

Nimk Game

现在有 n 堆石子,第 i 堆有 ai 个。双人博弈,每次从至多 k 个当前非空的石子堆当中取至少一个。无法操作者输。问最后谁会获胜。

n,k105,ai109

Crosses and Crosses Game

有一个 1×n 的纸条,初始全部为空。双人博弈,每次选取一个空白的位置涂黑。第一个满足 “操作后有连续三个位置被涂黑” 的人获胜。问最后谁会获胜。

n5000

K倍动态减法游戏

HDUOJ A simple stone game

各种棋盘游戏(Chess Game)

有一个 m×m 的棋盘和 n 个棋子,初始位置给定。双人博弈,每次选取一个在 (x,y)的棋子移动到 (xk,y)(x,yk)(xk,yk)。第一个将其中一个棋子放置到 (0,0) 的人获胜。问最后谁会获胜。

m100

POJ A Chess Game

各种翻转游戏(Ruler Game)

n 个硬币排成一排,其中 m 个初始向上,其余向下。双人博弈,每次选取一个区间,并将区间内的硬币全部翻面,要求区间右端点的硬是从向上翻到向下。无法操作者输,问最后谁会获胜。

n109,m105

HDUOJ 朋友

洛谷 P3179 [HAOI2015] 数组游戏

各种数字游戏(Number Game)

POJ A multiplication game

解:平等博弈,

初始有两个数 a,b。双人博弈,每次操作依次进行:

  • 如果 a>b,则交换 a,b

  • 如果 a=0,则当前玩家失败,游戏结束;

  • 玩家选择:将 b 变为 bmoda,或者选定一个 k1 并将 b 减去 ak

问最后谁会获胜。

a,b1018

各种树上游戏(Tree Game)

洛谷 [AGC010F] Tree Game

完整代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3e3 + 9;
struct Edge{
	int v, nex;
} e[N << 1];
int head[N], ecnt;
void addEdge(int u, int v){
	e[++ecnt] = Edge{v, head[u]};
	head[u] = ecnt;
}
int a[N], n;
bool dfs(int u, int fa){
	for(int i = head[u]; i; i = e[i].nex){
		int v = e[i].v;
		if(v == fa)
			continue;
		if(a[u] > a[v] && !dfs(v, u))
			return true;
	}
	return false;
}
signed main(){
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	for(int i = 1; i < n; i++){
		int u, v;
		scanf("%lld%lld", &u, &v);
		addEdge(u, v);
		addEdge(v, u);
	}
	for(int i = 1; i <= n; i++)
		if(dfs(i, 0))
			printf("%lld ", i);
	return 0;
} 

洛谷 [AGC014D] Black and White Tree

HDUOJ Gameia

Green Hackenbush Game

现在有一棵有根树。双人博弈,每次可切断一条边,保留包含根的部分。无法操作者输。问最后谁会获胜。

n105

posted @   JPGOJCZX  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示