博弈问题总结
什么是组合游戏——
(1) 有两个玩家;
(2) 游戏的操作状态是一个有限的集合(比如:限定大小的棋盘);
(3) 游戏双方轮流操作;
(4) 双方的每次操作必须符合游戏规定;
(5) 当一方不能将游戏继续进行的时候,游戏结束,同时,对方为获胜方;
(6) 无论如何操作,游戏总能在有限次操作后结束;
概念:必败点和必胜点(P点 & N点)
(1) 所有终结点是必败点(P点);
(2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
(3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
取子游戏算法实现——
步骤1:将所有终结位置标记为必败点(P点);
步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)
步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ;
步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。
kiki's game hdu
题意:一开始在1,m的地方。每次可以往下,左下,左走一步,走到无法走的时候就输
当前步赢的条件是下一步有输的状态
用以上思想模拟,然后打出表来,找规律就能得出结论:n,m两个中有个是偶数就先手胜利。
Nim游戏简介
有两个玩家;
有三堆扑克牌(比如:可以分别是 5,7,9张);
游戏双方轮流操作;
玩家的每次操作是选择其中某一堆牌,然后从中取走任意张;
最后一次取牌的一方为获胜方;
引入概念:Nim-Sum
定义: 假设 (xm · · · x0)2 和(ym · · · y0)2 的nim-sum是(zm · · · z0)2,则我们表示成 (xm · · · x0)2 ⊕ (ym · · · y0)2 = (zm · · · z0)2, 这里,zk = xk + yk (mod 2)(k=0…m)
对于nim游戏的某个位置(x1,x2,x3),当且仅当它各部分的nim-sum等于0时(即x1⊕x2⊕x3=0),则当前位于(P点)。
定理一也适用于更多堆的情况~
Being a Good Boy in Spring Festival hdu
下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。
现在我们不想研究到底先手为胜还是为负,我只想问大家:
——“先手的人如果想赢,第一步有几种选择呢?”
一.
如果a1^a2^a3^...^an=0( 即 : nim-sum=0) , 说明先手没有必赢策略, 方法数肯定为 0;
二.
假设先手的人有必赢策略。
问题则转化为=>在任意一堆拿任意K张牌,并且剩下所有堆的nim-sum=0(P-position)的方案总数。
1. 现在我们先看一个例子(5,7,9),并假设从第一堆取任意K张牌。
排除第一堆牌的nim-sum为 7^9=14
0111
^1001
-------
1110
如果要使所有堆的nim-sum=0成立,则第一堆取掉K张以后必定为1110,因为X^X=0。所以要观察 5-k=14 k>0 成立,此例子(在第一堆取任意K张牌)明显的不成立。但并不代表在第二或第三堆取任意K张牌的解不成立。
2. 现在看第二个例子(15,7,9),并假设从第一堆取任意K张牌。
排队第一堆牌的nim-sum为7^9=14,和第一个例子相同,所以问题变为观察 15-k=14 k>0 是否成立。当然这个例子是成立的。
三.
总结得出:
在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立的条件为:排除取掉K张牌的那一堆的nim-sum必须少于该堆牌上的数量(例子二),否则不能在此堆上取任意K张牌使所有堆的nim-sum=0成立(例子一)。
故总方案数为 ( 在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立 ) 的总数。
Graph Game &
S-G函数
(1) 有向无环图
(2) 玩家1先移动,起点是x0
(3) 两个玩家轮流移动
(4) 对于顶点x, 玩家能够移动到的顶点集记为F(x).
(5) 不能移动的玩家会输掉游戏
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、 mex{2,3,5}=0、mex{}=0。
定义: 一个图的Sprague-Grundy函数(X,F)是定义在X上的非负函数g(x),并且满足:
g(x) = mex{g(y) : y∈F(x)}
P-点: 即令 g(x) = 0 的 x 点!
N-点: 即令 g(x) > 0 的 x 点!
Sums of Combinatorial Games
假设游戏 Gi的SG函数是gi, i=1,…,n, 则
G = G1 + … + Gn 的 SG函数是
g(x1,…,xn) = g1(x1)⊕…⊕gn(xn).
sg函数的一般模板
int mex(int x) { bool use[maxn]={0}; for(int i=0;i<sn;++i) { int t=x-s[i]; if(t<0) break; if(g[t]==-1) g[t]=mex(t); use[g[t]]=1; } for(int i=0;;++i) { if(!use[i]) return i; } }
S-Nim hdu
nim取子的变形,但每次取子的数量只能是是s中集合的元素,求先手是否能胜。
每堆石子求出sg值,然后进行异或运算就好了。