(收集于网络)
博弈论:是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜目标的理论。博弈论是研究互动决策的理论。博弈可以分析自己与对手的利弊关系,从而确立自己在博弈中的优势,因此有不少博弈理论,可以帮助对弈者分析局势,从而采取相应策略,最终达到取胜的目的。(摘自百度百科)
(一)巴什博奕(Bash Game)
只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。
显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:每个回合时m+1个,如果n=(m+1)*r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。
这个游戏还可以有一种变相的玩法:两个人轮流报数,每次至少报一个,最多报十
个,谁能报到100者胜。
巴什博弈博弈论里面最简单的一种形式。以下题目利用巴什博弈可以轻松解决:
1. https://acm.hdu.edu.cn/showproblem.php?pid=1846 (brave game)
2. https://acm.hdu.edu.cn/showproblem.php?pid=2147 (kiki's game)
3. https://acm.hdu.edu.cn/showproblem.php?pid=2149 (public sale)
4. https://acm.hdu.edu.cn/showproblem.php?pid=2188 (选拔志愿者)
下面介绍分析此类题目的通用方法:P/N分析:
P点: 即必败点,某玩家位于此点,只要对方无失误,则必败;
N点: 即必胜点,某玩家位于此点,只要自己无失误,则必胜。
三个定理:
定理:
一、 所有终结点都是必败点P(上游戏中,轮到谁拿牌,还剩0张牌的时候,此人就输了,因为无牌可取);
二、所有一步能走到必败点P的就是N点;
三、通过一步操作只能到N点的就是P点;
如:
以上题目均可以通过P/N分析法来解决。
这几个题目都非常的简单。下面仅对2149做简单分析:(P/N分析也可以)
首先明确使用巴什博弈有个前提(特点)每次拿的数量是从1-m的不间断整数开始的。注意这一点很重要。无此条件巴什博弈不成立!
其实这个题目稍微动动脑就可以把它转换为巴什博弈(特点明显)。你就假设两人拍卖的时候是从给定的最高价开始—谁先拍卖到0谁就就是胜者。需要注意的是我们对特殊情况的考虑。
(二)Fibonacci’s Game(斐波那契博弈)
有一堆个数为n的石子,游戏双方轮流取石子,满足:
1)先手不能在第一次把所有的石子取完;
2)之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)。
约定取走最后一个石子的人为赢家,求必败态。
这个和之前的Wythoff’s Game 和取石子游戏 有一个很大的不同点,就是游戏规则的动态化。之前的规则中,每次可以取的石子的策略集合是基本固定的,但是这次有规则2:一方每次可以取的石子数依赖于对手刚才取的石子数。
这个游戏叫做Fibonacci Nim,肯定和Fibonacci数列:f[n]:1,2,3,5,8,13,21,34,55,89,… 有密切的关系。如果试验一番之后,可以猜测:先手胜当且仅当n不是Fibonacci数。换句话说,必败态构成Fibonacci数列。
就像“Wythoff博弈”需要“Beatty定理”来帮忙一样,这里需要借助“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和。定理的证明可以在这里 看到,不过我觉得更重要的是自己动手分解一下。
比如,我们要分解83,注意到83被夹在55和89之间,于是把83可以写成83=55+28;然后再想办法分解28,28被夹在21和34之间,于是28=21+7;依此类推 7=5+2,故 ;
如果n=83,我们看看这个分解有什么指导意义:假如先手取2颗,那么后手无法取5颗或更多,而5是一个Fibonacci数,如果猜测正确的话,(面临这5颗的先手实际上是整个游戏的后手)那么一定是先手取走这5颗石子中的最后一颗,而这个我们可以通过第二类归纳法来绕过,同样的道理,接下去先手取走接下来的后21颗中的最后一颗,再取走后55颗中的最后一颗,那么先手赢。
反过来如果n是Fibonacci数,比如n=89:记先手一开始所取的石子数为y,若y>=34颗(也就是89的向前两项),那么一定后手赢,因为89-34=55=34+21<2*34,所以只需要考虑先手第一次取得石子数y<34的情况即可,所以现在剩下的石子数x介于55到89之间,它一定不是一个Fibonacci数,于是我们把x分解成Fibonacci数:x=55+f[i]+…+f[j],若,如果f[j]<=2y,那么对B就是面临x局面的先手,所以根据之前的分析,B只要先取f[j]个即可,以后再按之前的分析就可保证必胜。
下证:f[j]<=2y
反证法:假设f[j]>2y,则 y < f[j]/2 = (f[j-1] + f[j-2])/2 < f[j-1]
而最初的石子数是个斐波那契数,即 f[k]=x+y < f[k-1]+f[i]+…+f[j]+f[j-1] <= f[k-1]+f[i]+f[i-1] <= f[k-1]+f[k-2] <= f[k] (注意第一个不等号是严格的,矛盾!)
https://acm.nyist.net/JudgeOnline/problem.php?pid=135
https://acm.hdu.edu.cn/showproblem.php?pid=2516
(转)分析:
n = 2时输出second;
n = 3时也是输出second;
n = 4时,第一个人想获胜就必须先拿1个,这时剩余的石子数为3,此时无论第二个人如何取,第一个人都能赢,输出first;
n = 5时,first不可能获胜,因为他取2时,second直接取掉剩下的3个就会获胜,当他取1时,这样就变成了n为4的情形,所以输出的是second;
n = 6时,first只要去掉1个,就可以让局势变成n为5的情形,所以输出的是first;
n = 7时,first取掉2个,局势变成n为5的情形,故first赢,所以输出的是first;
n = 8时,当first取1的时候,局势变为7的情形,第二个人可赢,first取2的时候,局势变成n为6得到情形,也是第二个人赢,取3的时候,second直接取掉剩下的5个,所以n = 8时,输出的是second;
…………
从上面的分析可以看出,n为2、3、5、8时,这些都是输出second,即必败点,仔细的人会发现这些满足斐波那契数的规律,可以推断13也是一个必败点。
借助“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和。n=12时,只要谁能使石子剩下8且此次取子没超过3就能获胜。因此可以把12看成8+4,把8看成一个站,等价与对4进行"气喘操作"。又如13,13=8+5,5本来就是必败态,得出13也是必败态。也就是说,只要是斐波那契数,都是必败点。
所以我们可以利用斐波那契数的公式:fib[i] = fib[i-1] + fib[i-2],只要n是斐波那契数就输出second。
(三)威佐夫博奕(Wythoff Game)
有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这种情况下是颇为复杂的。我们用(ak,bk)(ak ≤ bk ,k=0,1,2,…,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k,奇异局势有
如下三条性质:
1。任何自然数都包含在一个且仅有一个奇异局势中。
由于ak是未在前面出现过的最小自然数,所以有ak > ak-1 ,而 bk= ak + k > ak-1 + k-1 = bk-1 > ak-1 。所以性质1。成立。
2。任意操作都可将奇异局势变为非奇异局势。
事实上,若只改变奇异局势(ak,bk)的某一个分量,那么另一个分量不可能在其他奇异局势中,所以必然是非奇异局势。如果使(ak,bk)的两个分量同时减少,则由于其差不变,且不可能是其他奇异局势的差,因此也是非奇异局势。
3。采用适当的方法,可以将非奇异局势变为奇异局势。
假设面对的局势是(a,b),若 b = a,则同时从两堆中取走 a 个物体,就变为了奇异局势(0,0);如果a = ak ,b > bk,那么,取走b – bk个物体,即变为奇异局势;如果 a = ak , b < bk ,则同时从两堆中拿走 ak – ab – ak个物体,变为奇异局势( ab – ak , ab – ak+ b – ak);如果a > ak ,b= ak + k,则从第一堆中拿走多余的数量a – ak 即可;如果a < ak ,b= ak + k,分两种情况,第一种,a=aj (j < k),从第二堆里面拿走 b – bj 即可;第二种,a=bj (j < k),从第二堆里面拿走 b – aj 即可。
从如上性质可知,两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。
那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:
ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括号表示取整函数)
奇妙的是其中出现了黄金分割数(1+√5)/2 = 1。618…,因此,由ak,bk组成的矩形近似为黄金矩形,由于2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[(1+√5)/2],那么a = aj,bj = aj + j,若不等于,那么a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那么就不是奇异局势。然后再按照上述法则进行,一定会遇到奇异局势。
https://acm.nyist.net/JudgeOnline/problem.php?pid=161
(三)尼姆博奕(Nimm Game)
有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这种情况最有意思,它与二进制有密切关系,我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。
计算机算法里面有一种叫做按位模2加,也叫做异或的运算,我们用符号(+)表示这种运算。这种运算和一般加法不同的一点是1+1=0。先看(1,2,3)的按位模2加的结果:
1 =二进制01
2 =二进制10
3 =二进制11 (+)
———————
0 =二进制00 (注意不进位)
对于奇异局势(0,n,n)也一样,结果也是0。
任何奇异局势(a,b,c)都有a(+)b(+)c =0。
如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?假设 a < b< c,我们只要将 c 变为 a(+)b,即可,因为有如下的运算结果: a(+)b(+)(a(+)b)=(a(+)a)(+)(b(+)b)=0(+)0=0。要将c 变为a(+)b,只要从 c中减去 c-(a(+)b)即可。
例1。(14,21,39),14(+)21=27,39-27=12,所以从39中拿走12个物体即可达到奇异局势(14,21,27)。
例2。(55,81,121),55(+)81=102,121-102=19,所以从121中拿走19个物品
就形成了奇异局势(55,81,102)。
例3。(29,45,58),29(+)45=48,58-48=10,从58中拿走10个,变为(29,4
5,48)。
下面先是一道简单的尼姆博弈题目
https://acm.hdu.edu.cn/showproblem.php?pid=1850
只要运用上面的知识即可解决(具体细节见代码)
然而这并不是博弈的重点,LCY老师讲到博弈之王道乃是SG值(具体见 https://acm.hdu.edu.cn/forum/read.php?tid=6875)。
SG值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。
我的理解:在步骤允许的情况下,与前面一个必败点的差(也就是说这个差是规定的、能走的、其中一个步数)!
后继点:也就是按照题目要求的走法(比如取石子可以取的数量,方法)能够走一步达到的那个点。(sg值的理解很抽象。我的队友mo、xi说多画画就可以了)
现在我们拿https://acm.hdu.edu.cn/showproblem.php?pid=1847这道题分析一下。
我们枚举下牌数为2-10的sg值:(SG(x)=mex{SG(x-S[i])}。)
num: 2 3 4 5 6 7 8 9 10
sg值: 2 0 1 2 0 1 2 0 1
具体的代码如下:(当然这题用P/N分析要简单得多,这里仅理解sg值)
- #include<cstdio>
- #include<algorithm>
- using namespace std;
- #define N 1000+10
- int arr[11],sg[N];
- int pre()//把1000以内的所有的可能一次拿的牌都算出来!
- {
- arr[0]=1;
- for(int i=1;i<=10;i++) arr[i]=arr[i-1]*2;
- return 0;
- }
- int mex(int x)//这是求解改点的sg值的算法函数(采用记忆化搜索)
- {
- if(sg[x]!=-1) return sg[x];
- bool vis[N];
- memset(vis,false,sizeof(vis));
- for(int i=0;i<10;i++)
- {
- int temp=x-arr[i];
- if(temp<0) break;
- sg[temp]=mex(temp);
- vis[sg[temp]]=true;
- }
- for(int i=0;;i++)
- {
- if(!vis[i])
- {
- sg[x]=i; break;
- }
- }
- return sg[x];
- }
- int main()
- {
- freopen("game.in","r",stdin); freopen("game.out","w",stdout);
- int num;
- pre();
- while(scanf("%d",&num)!=EOF)
- {
- memset(sg,-1,sizeof(sg));
- if(mex(num)) printf("Kiki/n");
- else printf("Cici/n");
- }
- return 0;
- }
题目1:今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根,可将一堆全取走,但不可不取,最后取完者为胜,求必胜的方法。
题目2:今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根,可将一堆全取走,但不可不取,最后取完者为负,求必胜的方法。
题目1 :尼姆博奕(Nimm Game)
题目2 : 先者必败条件: 奇异局势&& 充裕堆数目>=2 或者 非奇异局势&& 孤单堆数目==n
详解:点击博弈知识汇总
推荐HDOJ题目
https://acm.hdu.edu.cn/showproblem.php?pid=1907
https://acm.hdu.edu.cn/showproblem.php?pid=2509
主要是后继点和SG值的问题:
SG值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。
后继点:也就是按照题目要求的走法(比如取石子可以取的数量,方法)能够走一步达到的那个点。
具体的有关SG值是怎么运用的希望大家自己多想想。
课件后面有一个1536的代码。可以放在后面做做
看到这里推荐大家做几道题:1846(最简单的博弈水题)
1847(求SG值)
有了上面的知识接下来我们来看看组合博弈(n堆石子)
推荐大家看个资料:
博弈-取石子游戏(推荐等级五星级)
https://acm.hdu.edu.cn/forum/read.php?fid=20&tid=5748
https://hi.baidu.com/netnode/blog/item/30932c2edc7384514fc226ea.html
这里提出了一个奇异状态的问题。看了这篇文章你会发现异或运算在博弈中使用的妙处。当然这里指出的只是组合博弈中一种特殊情况。
王道还是对SG值的求解,但是知道这么一种思路无疑对思维的广度和深度扩展是很有帮助的。
ZZ博弈
https://acm.hdu.edu.cn/forum/read.php?fid=9&tid=10617
这里介绍了组和博弈的两种大的类型,一种是最后取的是N状态一种是最后取的是P状态,两个状态的解题方法能看懂很有帮助。当然,能够把推导过程理解,吃透无疑是大牛级的做法~小子也佩服的紧~
1536题推荐做做这题,这题前面提醒大家是一个求SG值的题目,题目前面是对异或运算运用在组合博弈问题中的很好的解释。当然题目本身是有所不同的。因为在这里面对取法有所要求。那么这样就回归到了解决博弈问题的王道算法——求SG值上。
有关运用求SG值的博弈题目有: 1850(也可基于奇异状态异或)
1848(中和的大斐波那契数列的典型求SG值题)
1517(个人认为有点猥琐的题目。。。。在此题上困扰很久。当然搞出来很开心。小子是用比较规矩的求SG值的方法求出来的,但是论坛有人对其推出来了规律,这里佩服一下,大家可以学习一下)
1079(更猥琐的题目,对新手要求较高,因为按传统方法需要比较细致的模拟加对边角状态的考虑,同样有人推出来了公式)
当你全部看完以上的东西。做完以上的题目的话。。。小子恭喜你~你博弈入门了~~~~
这里小子告诉大家。博弈很强大。学习要耐心~谢谢
Current System Time : 2008-12-11 19:16:03
ACM课作业:
1001 Brave Game
1002 Good Luck in CET-4 Everybody!
1003 Fibonacci again and again
1004 Rabbit and Grass
1005 Being a Good Boy in Spring Festival
1006 Public Sale
1007 悼念512汶川大地震遇难同胞——选拔志愿者
1008 kiki’s game
1009 Calendar Game
1010 A Multiplication Game
1011 Digital Deletions
1012 S-Nim
https://acm.hdu.edu.cn/forum/read.php?tid=11339&fpage=0&toread=&page=1
(四)最后我们来看组合博弈:(博弈的精华)
博弈-取石子游戏
https://acm.hdu.edu.cn/forum/read.php?fid=20&tid=5748
https://hi.baidu.com/netnode/blog/item/30932c2edc7384514fc226ea.html
组合博弈无疑是对sg值的熟练操作例如:有n堆石子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗…… 我们可以把它看作3个子游戏,第1个子游戏只有一堆石子,每次可以取1、2、3颗,很容易看出x颗石子的局面的SG值是x%4。第2个子游戏也是只有一堆 石子,每次可以取奇数颗,经过简单的画图可以知道这个游戏有x颗石子时的SG值是x%2。第3个游戏有n-2堆石子,就是一个Nim游戏。对于原游戏的每 个局面,把三个子游戏的SG值异或一下就得到了整个游戏的SG值,然后就可以根据这个SG值判断是否有必胜策略以及做出决策了。其实看作3个子游戏还是保 守了些,干脆看作n个子游戏,其中第1、2个子游戏如上所述,第3个及以后的子游戏都是“1堆石子,每次取几颗都可以”,称为“任取石子游戏”,这个超简单的游戏有x颗石子的SG值显然就是x。