博弈论
base
公平组合游戏
无偏博弈:任意局势游戏双方都是平等的回合制双人游戏,平等的含义时当前的所有可行的走法仅仅只依赖当前的局势,与当前谁移动无关
- 游戏有两个人参与,二者轮流做出决策,双方均知道游戏的完整信息;
- 任意一个游戏者在某一确定状态可以作出的决策集合只与当前的状态有关,而与游戏者无关;
- 游戏中的同一个状态不可能多次抵达,游戏以玩家无法行动为结束,且游戏一定会在有限步后以非平局结束
必胜点&必败点
(P)点:必败点,在双方都聪明无比的情况下,当前先手必败的位置
(N)点:必胜点,在双方都聪明无比的情况下,当前先手必胜的位置
几个性质:
所有的终止位置都是必败点(P)
从任何一个必胜点(N)操作,至少有一种方法可以到达一个必败点(P)
从一个必败点(P)出发,只能到达一个必胜点(N)
常见模型:
巴什博奕((Bash GameBash Game)) 威佐夫博弈((Wythoff GameWythoff Game)) 尼姆游戏$(Nim GameNim Game) $ (Anti−SG)游戏 (Multi−SG)游戏 (Every−SG)游戏 翻硬币游戏 树上删边游戏
博弈图和状态
如果将每个状态视为一个节点 再从每个状态向它的后继状态连边 就可得到一个博弈状态图
定义 必胜状态 为 先手必胜的状态 , 必败状态 为 先手必败的状态 。
通过推理,可以得出下面三条定理:
- 定理 1:没有后继状态的状态是必败状态。
- 定理 2:一个状态是必胜状态当且仅当存在至少一个必败状态为它的后继状态。
- 定理 3:一个状态是必败状态当且仅当它的所有后继状态均为必胜状态。
如果博弈图是一个有向无环图,则通过这三个定理,我们可以在绘出博弈图的情况下用(O(N+M))的时间(其中(N)为状态种数,(M)为边数)得出每个状态是必胜状态还是必败状态。
Nim游戏
(n)堆物品,每堆有(a_i)个,两个玩家轮流取走任意一堆的任意个物品,但不能不取。取走最后一个物品的人获胜。
通过绘画博弈图,可以在(O(Pi _{i=1}^n a_i))的时间内求出该局是否先手必赢 but,这个时间复杂度太高辽
定义(Nim)和(=a_1oplus a_2oplus...oplus a_n)
当且仅当(Nim)和为(0)时,该状态为必败状态 否则该状态为必胜状态
证明:
为什么异或值和状态的胜负有关?
只需证明下面三个定理:
- 定理1:没有后继状态的状态为必败状态
- 定理2:对于(a_1oplus a_2oplus...oplus a_n ot=0)的局面,一定存在某种移动使得(a_1oplus a_2oplus...oplus a_n=0)
- 定理3:对于(a_1oplus a_2oplus...oplus a_n=0)的局面,一定不存在某种移动使得(a_1oplus a_2oplus...oplus a_n)
定理1:没有后继状态的状态只有一个,即全(0)局面 此时(a_1oplus a_2oplus...oplus a_n=0)
定理2:不妨假设(a_1oplus a_2oplus...oplus a_n=k ot=0) 如果我们将(a_i)改为(a_i'),则(a_i'=a_ioplus k)
设(k)在二进制下最高位的(1)在第(x)为 则一定有奇数个(a_i)二进制下在(x)位为(1)
定理3:若要将(a_i)改为(a_i'),根据异或运算律可以得出(a_i=a_i'),因而这不是个合法的移动
(==还是不太懂怎么办! 记住就是了)
SG
(Sprague-Grundy)定理:所有一般胜利下的无偏博弈都能转化成尼姆数表达的尼姆堆博弈,一个无偏博弈的尼姆值定义为这个博弈的等价尼姆数
即:对于当前游戏(X),它可以拆分成若干个子游戏(x_1,x_2,...,x_n) 那么(SG(X)=SG(x_1)oplus SG(x_2)oplus...oplus SG(x_n))
定义(mex)函数的值为不属于集合(S)中的最小非负整数 (eg:mex({0,2,4})=1,mex({phi})=0)
对于状态(x)和它的所有(k)个后继状态(y_1,y_2,...,y_k) 定义(SG)函数:(SG(x)=mex{SG(y_1),SG(y_2),...,SG(y_k)})
而对于由(n)个有向图游戏组成的组合游戏 设它们的起点分别为(s_1,s_2,...,s_n),则当且仅当(SG(s_1)oplus SG(s_2)oplus...oplus SG(s_n) ot=0)时,这个游戏为先手必胜
巴什博弈(Bash Game)
有(1)堆石子,总个数是(n),两名玩家轮流在石子堆中拿石子,每次至少取(1)个,至多取(m)个。取走最后一个石子的玩家为胜者。判定先手和后手谁胜。
若((m+1)|n) 则先手必败 否则先手必胜
证明:
当(nle m)时,显然先手获胜
当(n=m+1)时,先手最多可取走(m)个,无论其取走多少个,剩下的后手总能一次取完
若((m+1)|n),假设先手拿走了(x)个,那么后手一定可以拿走((m+1)-x)个,这样无论怎么拿剩下的石头个数都将是(m+1)的倍数。那么最后一次取的时候石头个数必定还剩下(m+1)个 即后面那种情况
否则的话,先手可以取走模(m+1)余数个数的石头 此时转换为((m+1)|n)的局面即后手必败
int main(){
rd(n),rd(m);
if(n%(m+1)) puts("first win");
else puts("second win");
return 0;
}
bool vis[N];int sg[N];
void SG(int n,int m){
for(int i=0;i<=n;++i){
memset(vis,0,sizeof(vis));
for(int j=max(i-m,0),j<i;++j) vis[sg[j]]=1;
for(int j=0;j<=n;++j)
if(!vis[j]) {sg[i]=j;break;}
}
}
int main(){
rd(n),rd(m);
SG(n,m);
puts(sg[n]?"first win":"second win");
return 0;
}
威佐夫博弈((Wythoff Game))
有两堆石子,石子数可以不同。两人轮流取石子,每次可以在一堆中取,或者从两堆中取走相同个数的石子,数量不限,取走最后一个石头的人获胜。判定先手是否必胜。
先手必败的状态形如(([i imesphi],[i imesphi^2])) 其中(phi=frac{sqrt5+1}2) ([x])表示不大于(x)的最大整数
int main(){
rd(a),rd(b);
if(a>b) swap(a,b);
int ans=(b-a)*((1.0+sqrt(5.0))/2.0);
if(ans==a) puts("0");
else puts("1");
return 0;
}