省赛前先练着,回来补完
巴什博弈: 一堆n个物品两个人来拿,每人至少拿一个,最多拿m个,问最后取完的人win
判断条件:n%(m+1)!=0
cin>> n>>m;
if (n%(m+1)!=0)
cout<<first win<<endl;
else
cout<<second win<<endl;
威佐夫博弈:两堆物品a,b,有两个人轮流来取,从一堆中取至少一个没有上限,或者从两堆中取相同数量的物品。两堆最后都取完的人win
判断点:(b-a)*(1+sqrt(5))/2,b为ab中的最大值,
cin>>a>>b;
if(a>b) swap(a,b);
int temp=(b-a)*(1+sqrt(5))/2;
if(temp==a) cout<<second win<<endl;
else cout<<first win<<endl;
nim博弈:有n堆物品每堆数量无限制,两个人从第一堆开始取,每次取至少一个没有上限,最后全取完的人win
判断条件 ans^=num
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){
cin>>num;
ans^=num;
}
if(ans) cout<<first win<<endl;
else cout<<second win<<endl;
fib博弈:一堆若干物品,两人轮流取物品,先手第一次不能把物品取完但后手可以(没必要),每次最少取一个,最多取对手最近一次所取物品的二倍,最后将物品取完的是人win
取法很奇怪应该是特定题目的解法,判断条件是一开始的物品数为斐波那契数则先手必败,打个表取找找就行。
日常贴带佬文章orz
SG函数:记打表公式,根据打表去找规律,寻找sg函数为0的特殊点,原理是拆成部分博弈类似nim博弈
转载大佬bestsort博客orz
//f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理
//SG[]:0~n的SG函数值
//S[]:为x后继状态的集合
int f[N],SG[MAXN],S[MAXN];
void getSG(int n){
int i,j;
memset(SG,0,sizeof(SG));
//因为SG[0]始终等于0,所以i从1开始
for(i = 1; i <= n; i++){
//每一次都要将上一状态 的 后继集合 重置
memset(S,0,sizeof(S));
for(j = 0; f[j] <= i && j <= N; j++)
S[SG[i-f[j]]] = 1; //将后继状态的SG函数值进行标记
for(j = 0;; j++) if(!S[j]){
//查询当前后继状态SG值中最小的非零值
SG[i] = j;
break;
}
}
}