博弈论

发布时间 2023-08-02 20:50:37作者: RReally

概念

1、平等组合游戏

  • 两人游戏,两人轮流走步
  • 有一个状态集,而且通常是有限的
  • 有一个终止状态,到达终止状态后游戏结束
  • 游戏可以在有限的步数内结束
  • 规定好了哪些状态转移是合法的
  • 所有规定对于两人是一样的

象棋围棋并不满足最后一个条件,因为双方可移动的策略并不相同

下面的均是在平等组合游戏的前提下讨论

2、N状态(必胜)P状态(必败)

对于最后走的人获胜的情况:

在保证最优策略情况下,这两种状态有三个准则

  • 所有的终止状态都为P状态
  • 对于任意的N状态,存在至少一条路径可以转移到P状态
  • 对于任意的P状态,只能转移到N状态

类型

例一:经典1、2、3石子

有A和B两个竞争者,有n个石子,每次可取1、2、3颗,A先手,取走最后一个的人获胜

问题:A能否保证自己胜利

\(n=4*k\), \(k\)为非负整数时A必败

因为B总能取走和A的数和为4的石子,一定最后取到最后一个

当不是该情况时,A可以先手构造出B的先手必败情况,所以A必胜

例二:取走特定数的石子

有A和B两个竞争者,有n个石子,每次可取\(p[1]\),\(p[2]\),\(p[3]\)\(……\)\(p[k]\)颗,A先手,取走最后一个的人获胜
那么,AA还有必胜策略吗?

有没有必胜策略,我们关键是要找到哪些状态是P状态,哪些状态是N状态.

不过,本题没有那么容易判断,因此我们需要引入一个新东西——\(SG\)函数

为了方便理解:我们先对每个状态(这里是剩余的石子数)设一个点,对于状态\(u\),通过一次操作能够到达的状态为其的儿子节点,连单向边

定义\(SG(x)\)为x的后继节点的SG值构成的集合执行\(mex()\)运算后的值

\(mex()\):设集合S是一个非负整数集合,mex(S)就是求不属于S的最小非负整数。

放个图

通过这里也可以更好的理解前面的三个准则

定理1:同一个图上
对于一个图GG,如果SG(G)!=0,则先手必胜,反之必败

证明:

若SG(begin)=!0

1.根据性质2,先手必可以走向0,
2.因此留给后手的是0,根据性质3,后手只能走向非0
3.以此类推,后手始终无法走向0,后手永远处于非0,当先手到达终点的0时,先手获胜
反之同理,必败

点击查看代码
 
#include<bits/stdc++.h>
#define int long long
#define pdd pair<double ,double >
 
using namespace std;
const int N = 110, M = 10010;
int n,m;
int s[N], f[M];
int sg(int x){
  if(f[x]!=-1) return f[x];
 
  unordered_set<int> S;
  for(int i=0;i<n;i++)
  //如果可以减去s[i],则添加到S中
    if(x>=s[i]) S.insert(sg(x-s[i]));
 
  //求mex(),即找到最小并不在原集合中的数
  for(int i=0; ; i++)
    if(!S.count(i)) return f[x]=i;
}
void solve(){
   cin>>n;
   for(int i=0;i<n;i++) cin>>s[i];
   memset(f,-1,sizeof f);
   cin>>m;
   int ans=0;
   while(m--){
    int x;cin>>x;
    ans^=sg(x);
   }
   if(ans) puts("Yes");
   else puts("No");
} 
 
signed main(){
  int t=1;
  // cin>>t;
  while(t--)
  solve();
  return 0;
}

待补