博弈问题(实时更新)

0. 参考文章

https://blog.csdn.net/weixin_38686780/article/details/82940573
https://blog.csdn.net/qq_41552508/article/details/89159952
https://www.zhihu.com/question/27467617

1. 平等博弈

1.1 常见概念及定理
1.1.1 组合游戏

公平组合游戏ICG – Impartial Combinatorial Games
游戏的胜负仅仅取决于当前状态,与谁在玩没有关系。
判定:

  1. 2人博弈
  2. 当前状态的下一个状态的个数有限
  3. 每个状态,两人操作集合相同
  4. 交替移动
  5. 一个人不能移动就为输
  6. 有限步内终止
1.1.2 P状态与N状态

P - 必败态
N - 必胜态

  1. 所有终止的状态是P状态
  2. 能一步到达P状态的是N状态
  3. 每一步都将到达N状态的为P状态
1.1.3 SG函数和SG定理

sg函数值的意义,如果 s g ( x ) = 0 sg(x)=0 sg(x)=0,那么x是必败态,否则x是必胜态。
定义: s g ( x ) = m i n { n ≥ 0 ∣ n = s g ( y ) , y ∈ F ( x ) } sg(x)=min\{n\geq 0|n=sg(y),y\in F(x)\} sg(x)=min{n0n=sg(y),yF(x)}
F ( x ) F(x) F(x)表示x所有的下一个状态的集合。
定义mex函数为不在一个集合里的最小非负整数。则
s g ( x ) = m e x { s g ( y ) ∣ y ∈ F ( x ) } sg(x)=mex\{sg(y)|y\in F(x)\} sg(x)=mex{sg(y)yF(x)}

SG定理:
s g ( x 1 , x 2 , . . . , x n ) = s g ( x 1 ) ⊕ s g ( x 2 ) ⊕ . . . ⊕ s g ( x n ) sg(x_1,x_2,...,x_n)=sg(x_1) \oplus sg(x_2)\oplus ... \oplus sg(x_n) sg(x1,x2,...,xn)=sg(x1)sg(x2)...sg(xn)

求sg函数代码:

const int maxn = 5e4 + 10;

//f[i]代表可行的转移方式 k代表方式总数

int f[maxn], k, sg[maxn];
bool vis[maxn];

void getsg(int n) {
    memset(sg, 0, sizeof sg);
    for (int i = 1; i <= n; ++i) {
        memset(vis, 0, sizeof vis);
        for (int j = 1; f[j] <= i && j <= k; ++j) {
            vis[sg[i - f[j]]] = 1;
        }
        for (int j = 0;; ++j)
            if (!vis[j]) {
                sg[i] = j;
                break;
            }
    }
}

1.2 常见模型
1.2.1 巴什博弈

一堆n个物品,每人每次轮流从中取出 1 − m 1 - m 1m个,最后取光者胜。
结论:如果 n % ( m + 1 ) = = 0 n \% (m+1)==0 n%(m+1)==0那么后手胜,否则先手获胜。

1.2.2 nim博弈

两个人玩取石子游戏,共有N堆石子,每个人每次可以从一堆石子里面任意多个石子,最后取光者胜。
结论:亦或和为0先手必败,否则先手必胜。

阶梯nim:n级台阶,每级台阶上放有石子。每人每次选一级台阶上的若干石子移到下一层。第0层为地面。不能移动的为输。
结论:奇数级台阶的亦或和为0先手必败,否则先手必胜。

1.2.3 反nim博弈

将nim改为最后取的人输。
必胜态有两种:

  1. 所有石堆个数都是1,且有偶数堆。
  2. 如果存在某堆个数不为1,那么亦或和不为0。
1.2.4 威佐夫博弈

两个人玩取石子游戏,共有2堆石子,每个人可以选择从一堆石子里面取石子,也可以选择从两堆石子里面取相同数量的石子,最后取光者胜。
结论:必败局势为(a,b)(a<b),满足
a = ( i n t ) ( b − a ) ∗ 5 + 1 2 a=(int)(b-a)*\frac{\sqrt{5}+1}{2} a=(int)(ba)25 +1

代码:

		if (x > y)swap(x, y);
        double r = (sqrt(5.0) + 1) / 2;
        if ((int) ((double) (y - x) * r) == x)cout << "houshou" << endl;
        else cout << "xianshou" << endl;
1.2.5 Moore’s Nimk

两个人玩取石子游戏,共有N堆石子,每个人每次可以从至多k堆石子里面任意多个石子,最后取光者胜。
结论:把n堆石子的石子数用二进制表示,统计每个二进制位上1的个数,若每一位上1的个数mod(k+1)全部为0,则必败。

1.2.6 Fibonacci博弈

1堆石子有n个,两人轮流取。先取者第1次可以取任意多个,但不能全部取完。以后每次取的石子数不能超过上次取子数的2倍。最后取光者胜。
结论:先手必胜当且仅当识字数n不是Fibonacci数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值