【算法与数据结构】——博弈论


参考文章

  1. ACM-博弈论基础
  2. 博弈论进阶之SG函数
  3. 博弈论 SG函数
  4. 《博弈论全家桶》(ACM / OI)(超全的博弈论 / 组合游戏大合集)
  5. SG函数及SG定理详解+证明

题目

【题目记录】——2021“MINIEYE杯”中国大学生算法设计超级联赛(8)
GCD Game
【题目记录】——2021牛客暑期多校训练营1
A题目地址
【题目记录】——ICPC南京
ICPC 南京A题

公平组合游戏

公平组合游戏是一种简单的博弈论
若一个游戏满足:

  1. 由两名玩家交替行动
  2. 在游戏进行的任意时刻,可以执行的合法行动与轮到哪位玩家无关
  3. 不能行动的玩家判负

则称该游戏为一个公平组合游戏。
下面介绍的几种博弈游戏都属于公平组合游戏,

巴什博弈(Bash Game)

一堆n个物品,两个人轮流从中取出1~m个,最后取光者胜(不能继续取的人输)。

同余定理:n=k∗(m+1)+r,先者拿走r个,那么后者无论拿走多少个先者只要使数目和为m+1,那么先手必赢。反之若n=k∗(m+1),那么先手无论怎样都会输。

if (n % (m + 1))  return false;
else  return true;

斐波那契博弈(Fibonacci Nim Game)

一堆石子有n个,两人轮流取,先取者第一次可以去任意多个,但是不能取完,以后每次取的石子数不能超过上次取子数的2倍。取完者胜。
规律:先手胜当且仅当n不是斐波那契数。
证明
代码:

f[0] = f[1] = 1;
for (int i = 0; f[i - 1] < n; i++)
{
    f[i] = f[i - 1] + f[i - 2];
    if (f[i] == n)  return true;
}
return false;

威佐夫博弈(Wythoff Game)

有两堆各若干物品,两个人轮流从任意一堆中至少取出一个或者从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜。
这里的必输局势:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。从这些必输局势可以发现,每组的第一个是前面没有出现的最小正整数, a k = [ k ∗ ( 1 + 5 ) / 2 ] ak=[k∗(1+\sqrt{5})/2] ak=[k(1+5 )/2], b k = a k + k b_k=a_k+k bk=ak+k, k=0,1,2,3…。

所以,先求出差值,差值*黄金分割比 == 最小值的话后手赢,否者先手赢。

double r = (sqrt(5) + 1) / 2;
int d = abs(a - b) * r;
if (d != min(a, b))  return true;
else  false;

注:如果a,b的值非常大的话,需要高精度来计算这个double类型的r。

Nim博弈

看了很多博客都只是一个又一个结论,推导的完整过程并没有给出。这篇文章写得较为详细,可以参考,我在这里简要介绍结论以及条件。
在博弈论问题当中,我们通常会将先手必败的局面称为奇异局势。
在一个博弈问题当中,如果存在奇异局面,也就是必败局面,那么一定满足三个条件。

第一个条件是无法进行任何操作的局面是奇异局面。
第二个条件是可以移动到奇异局面的局面是非奇异局面。
第三个条件是在奇异局面当中所作的任何操作得到的都是非奇异局面。

我们可以通过二进制位来判断是否先手必胜。我们要判断每个二进制位当中出现的1的次数和是否是偶数,可以通过位运算的亦或来完成。如果每个二进制位当中出现的1的次数和是偶数,则是非奇异局势。在亦或操作当中,对每一个二进制位进行计算,奇数为1,偶数为0。所以我们只需要计算一下这三堆石子亦或之后的结果是否为0,就可以知道是否每一个二进制位的1的数量是否都是偶数了。

so代码如下:

//只需要判断所有石堆中石子的数量异或的结果即可。
bool win_or_lose(int *d,int n)
{
	bool res = 0;
	for(int i = 1;i <= n;i++)
	{
		res ^= a[i];
	}
	return res;
}

SG函数

首先定义mex(minimal excludant)运算,这是定义于一个集合的运算,表示最小的不属于这个集合的最小非负整数。例如mex{0,1,2,4}=3,mex{2,3,4}=0,mex{}=0.
SG函数(Sprague-Grundy):对于一个给定的有向无环图,定义关于这个图的每个顶点的SG函数如下:sg(x)=mex{sg(y) | y是x的后继}
SG函数的求法:

找出必败态
找出当前所有状态的前驱结点
根据定义计算结点SG值
重复上述步骤,直到整棵树建立完成

SG定理:所以我们可以定义有向图游戏的和。设G1,G2,…Gn为n个“有向图”游戏的和(Sum),游戏G的移动规则是:任选一个子游戏Gi并移动上面的棋子。SG定理就是:sg(G)=sg(G1)∧sg(G2)∧…∧sg(Gn)。也就是说,游戏的SG函数值就是它的所有子游戏的SG函数值的异或。
因此,当我们面对n个不同游组成的游戏时,只需要求出每个游戏的SG函数值,把这些SG值都看作Nim的石子堆,然后依照找Nim游戏的必胜策略的方法来找这个游戏的必胜策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值