【算法】简单博弈论

巴什博弈 (bash game)

题型

仅有一堆n个物品,两个人轮流取1~m个,最后取的人胜(不能取的人输)

分析

总体可分几种情况

  • $n=0$,先手输
  • $0<n<=m$,先手胜
  • $n=m+1$,先手输
  • $n=k*(m+1)+r$,先手胜(先手取走r个,给后手留下k*(m+1)的局面)
  • $n=k*(m+1)$,先手输

代码

int Bash_Game(int n,int m)    //是否先手有必赢策略
{
    if(n==0) return 0;
    if(n%(m+1)!=0) return 1;
    return 0;
}

尼姆博弈(Nim Game)

题型

将一堆变为多堆;
即:
有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜。

分析

本部分含其他博客内容

地址:https://www.cnblogs.com/jiangjun/archive/2012/11/01/2749937.html

  1. 首先自己想一下,就会发现只要最后剩两堆物品一样多(不为零),第三堆为零,那面对这种局势的一方就必败
  • 那我们用(a,b,c)表示某种局势,首先(0,0,0)显然是必败态,无论谁面对(0,0,0) ,都必然失败;第二种必败态是(0,n,n),自己在某一堆拿走k(k ≤ n)个物品,不论k为多少,对方只要在另一堆拿走k个物品,最后自己都将面临(0,0,0)的局势,必败。仔细分析一下,(1,2,3)也是必败态,无论自己如何拿,接下来对手都可以把局势变为(0,n,n)的情形
  • 那这种奇异局势有什么特点呢?
    也不知谁这么牛逼,竟然能把这种局势和二进制联系在一起
    这里说一种运算符号,异或’^’,a^b=a’b+ab’(a’为非a)
    我们用符号XOR表示这种运算,这种运算和一般加法不同的一点是1 XOR 1 = 0。先看(1,2,3)的按位模2加的结果:
    1 = 二进制01
    2 = 二进制10
    3 = 二进制11 XOR
    ———————
    0 = 二进制00 (注意不进位)
  • 对于奇异局势(0,n,n)也一样,结果也是0
    任何奇异局势(a,b,c)都有a XOR b XOR c = 0
  • 如果我们面对的是一个非必败态(a,b,c),要如何变为必败态呢?
    假设 a < b < c,我们只要将 c 变为a XOR b,即可。因为有如下的运算结果:
    a XOR b XOR (a XOR b)=(a XOR a) XOR (b XOR b) = 0 XOR 0 = 0
    要将c 变为a XOR b,只要对 c进行 c-(a XOR b)这样的运算即可
  1. 尼姆博弈模型可以推广到:有n堆若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
    这个游戏中的变量是堆数k和各堆的物品数N1,N2,……,Nk。
    对应的组合问题是,确定先手获胜还是后手获胜以及两个游戏人应该如何取物品才能保证自己获胜
  2. 为了进一步理解Nim取物品游戏,我们看看特殊情况。
    如果游戏开始时只有一堆物品,先手则通过取走所有的物品而获胜。现在设有2堆物品,且物品数量分别为N1和N2。游戏者取得胜利并不在于N1和N2的值具体是多少,而是取决于它们是否相等。
  • 也就说两堆的策略我们有了,现在我们如何从两堆的取子策略扩展到任意堆数中呢?
  • 首先回忆一下,每个正整数都有对应的一个二进制数,例如:57(10) = 111001(2) ,即:57(10)=25+24+23+20。于是,我们可以认为每一堆物品数由2的幂数的子堆组成。这样,含有57枚物品大堆就能看成是分别由数量为25、24、23、20的各个子堆组成
  • 现在考虑各大堆大小分别为N1,N2,……Nk的一般的Nim博弈。将每一个数Ni表示为其二进制数(数的位数相等,不等时在前面补0):
    N1 = as…a1a0
    N2 = bs…b1b0
    ……
    Nk = ms…m1m0
    如果每一种大小的子堆的个数都是偶数,我们就称Nim博弈是平衡的,而对应位相加是偶数的称为平衡位,否则称为非平衡位。因此,Nim博弈是平衡的,当且仅当:
    as +bs + … + ms 是偶数,即as XOR bs XOR … XOR ms = 0
    ……
    a1 +b1 + … + m1 是偶数,即a1 XOR b1 XOR … XOR m1 = 0
    a0 +b0 + … + m0是偶数,即a0 XOR b0 XOR … XOR m0 = 0
  • 于是,我们就能得出尼姆博弈中先手获胜策略:
    Bouton定理:先手能够在非平衡尼姆博弈中取胜,而后手能够在平衡的尼姆博弈中取胜。即状态(x1, x2, x3, …, xn)为P状态当且仅当x1 xor x2 xor x3 xor … xor xn =0。这样的操作也称为Nim和(Nim Sum)
    我们以一个两堆物品的尼姆博弈作为试验。设游戏开始时游戏处于非平衡状态。这样,先手就能通过一种取子方式使得他取子后留给后手的是一个平衡状态下的游戏,接着无论后手如何取子,再留给先手的一定是一个非平衡状态游戏,如此反复进行,当后手在最后一次平衡状态下取子后,先手便能一次性取走所有的物品而获胜。而如果游戏开始时游戏牌平衡状态,那根据上述方式取子,最终后手能获胜
  • 下面应用此获胜策略来考虑4堆的Nim博弈。其中各堆的大小分别为7,9,12,15枚硬币。用二进制表示各数分别为:0111,1001,1100和1111
    于是可得到如下一表:
  $2^{3}=8$ $2^{2}=4$ $2^{1}=2$ $2^{0}=1$
大小为7的堆 0 1 1 1
大小为9的堆 1 0 0 1
大小为12的堆 1 1 0 0
大小为15的堆 1 1 1 1

由Nim博弈的平衡条件可知,此游戏是一个非平衡状态的Nim博弈,因此,先手在按获胜策略一定能够取得最终的胜利。具体做法有多种,先手可以从大小为12的堆中取走11枚硬币,使得游戏达到平衡(如下表)

  $2^{3}=8$ $2^{2}=4$ $2^{1}=2$ $2^{0}=1$
大小为7的堆 0 1 1 1
大小为9的堆 1 0 0 1
大小为12的堆 0 0 0 1
大小为15的堆 1 1 1 1

之后,无论后手如何取子,先手在取子后仍使得游戏达到平衡
同样的道理,先手也可以选择大小为9的堆并取走5枚硬币而剩下4枚,或者,先手从大小为15的堆中取走13枚而留下2枚

  • 归根结底, Nim博弈的关键在于游戏开始时游戏处于何种状态(平衡或非平衡)和先手是否能够按照取子游戏的获胜策略来进行游戏

代码

int Nimm_Game(int n)   //假设n个数存在数组f[]中,有必胜策略返回1
{
    int sum=0;
    for(int i=1;i<=n;i++)
    sum^=f[i];
    if(sum) return 1;
    return 0;
}

?

原文地址:https://www.cnblogs.com/bbqub/p/8503822.html

时间: 2024-10-04 02:04:30

【算法】简单博弈论的相关文章

若干排序算法简单汇总(一)

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/35819279 作者:小马 从题目看,首先不是全部是若干.排序算法很多,我个人的能力也有限,不可能都讲到.另外,是简单汇总,是希望能用最简单的代码,最简短的语言说明问题,不搞太多理论分析. 就像前面说的,排序算法有很多,而且不存在哪一种最不好,哪一种最好这样的说法.根据用途不同选择最适合的就行了.不过仅从时间复杂度来看,基本上有两种,一种是O(n^2), 一种是O(nlogn).

若干排序算法简单汇总(二)

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/36706131 作者:小马 一希尔排序 上一篇讲到的直接插入排序,时间复杂度O(n^2). 请在脑海里想一下它的过程.如果一个序列本来就是有序的,对它排序的时间复杂度是O(n).所以当序列基本有序时,插入排序排序的效率大大提高,因为减少了移动的动作. 另外,直接插入排序还有一个特点,当n比较小时,它的效率比较高. 希尔排序正是基于上面两个思想做的一种改进算法.它先将整个序列分成若干

hdu 1312 DFS算法简单题

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 此题与油田那题很像是练习深搜的好题,题意是从"@"开始,遍历整个图,找到连接的 "."有多少个 但要考虑变化,简单处理下就行了,主要是斜角的不要了,而且判断结束方式也不一样 具体看代码吧 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

算法笔记_071:SPFA算法简单介绍(Java)

目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个顶点,称为起点,求取起点到其它所有顶点之间的最短距离,其显著特点是可以求含负权图的单源最短路径,且效率较高.(PS:引用自百度百科:spfa是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛

简单博弈论总结

简单博弈论 本次简单博弈论讲解六个知识点: 1:bash博弈:2:nim博弈:3:威佐夫博弈:4:Fibonacci博弈:5:sg函数: 首先介绍博弈论问题有如下几个特点 1:博弈模型为两人轮流决策的博弈.并且两人都使用最优策略来取得胜利. 两个玩家,都会采取最优的决策,那么如果存在一个局面为必胜局面,某玩家位于此局面.只要自己无失误,则必胜.那么同样又一个局面为必败局面,某玩家位于此局面.只要对手无失误,则必败. 那也就是说,针对这样的游戏,我们关注点应该在局面上. 2:博弈是有限的.即无论两

KMP 算法简单解释

KMP 算法简单解释 ? 讲KMP算法,离不开BF,实际上,KMP就是BF升级版,主要流程和BF一样,就是在削除回溯上花了点功夫,利用Next数组来削除 <( ̄︶ ̄)[GO!] 1. 先看看BF算法(暴力破解) int Brute_force_1(const char *S, const char *T) { if (!S || !T) return -1; int lenS = strlen(S); int lenT = strlen(T); int i = 0; //主串下标索引 int j

HMM的维特比算法简单示例

今天读了一位大牛的关于HMM的技术博客,读完之后,写了一个关于维特比算法的简单示例,用scala和java语言混合编写的.现在上传之. package com.txq.hmm import java.utilimport scala.collection._ /** * HMM维特比算法,根据显示状态链条估计隐式链条 * @param states 隐式states * @param observations 显式states * @param start_probability 初始概率向量

经典排序算法--简单选择排序

算法简介 简单选择排序是一种选择排序. 选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止. 白话理解 依然已排队为例,在排队时,有的老师可能会选择这样排序,先在一列中选出最矮的,放在第一位,然后选出第二矮的,放在第二位.队伍完成排序.而这就是选择排序的思想. 简单排序处理流程 (1)从待排序序列中,找到关键字最小的元素: (2)如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换: (3)从余下的 N - 1 个元素中,找出关键字最小

排序算法(简单排序,冒泡排序)

int[] a = new int[10]; for (int i = 0; i < a.length; i++) { a[i] = random(); System.out.print(a[i] + " "); } System.out.println(); int temp = 0; // 从小到大 // 简单选择排序法 // 方法1 int minIndex = 0; for (int i = 0; i < a.length - 1; i++) { minIndex