基础博弈
巴什博奕
一堆n个物品,两个人轮流从中取出1~m个,最后取光者胜(不能继续取的人输)。
同余定理:n=k∗(m+1)+r,先者拿走r个,那么后者无论拿走1 --m个先者只要的数目使和为m+1,那么先手必赢。反之若n=k∗(m+1),那么先手无论怎样都会输。
if (n % (m + 1)) return false; else return true;
威佐夫博弈
有两堆各若干物品,两个人轮流从任意一堆中至少取出一个或者从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜。
这里的必输局势:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
从这些必输局势可以发现,每组的第一个是前面没有出现的最小正整数。
所以,先求出差值,差值*黄金分割比等于最小值的话后手赢,否者先手赢。
double r = (sqrt(5) + 1) / 2;//黄金分割比 int d = abs(a - b) * r; if (d != min(a, b)) return true; else false;
斐波那契博弈
一堆石子有n个,两人轮流取,先取者第一次可以去任意多个,但是不能取完,以后每次取的石子数不能超过上次取子数的2倍。取完者胜。
同样是一个规律:先手胜当且仅当n不是斐波那契数。
f[0] = f[1] = 1; for (int i = 0; f[i - 1] < n; i++) { f[i] = f[i - 1] + f[i - 2]; if (f[i] == n) return true; } return false;
尼姆博弈
有n堆物品,两人轮流取,每次取某堆中不少于1个,最后取完者胜。
假如有3堆物品(a,b,c)
(0,0,0)状态时先手是一个必输局势因为没有东西可取,(0,n,n) 状态时也是必输局势只要后者在另一堆取得物品与前者一样多时那么前者也就是必输局势。
通过分析(1,2,3)也是一个必输局势。如果我们将其转化为二进制形式并通过异或运算(^)我们会发现:
0001^0010^0011=0000
通过验证所有的堆数量累^后只要为0就都是必输局势,所以我们就只要记住这个规则:将n堆物品数量全部异或后结果为0先手必败,否则必胜。
int res = 0; for (int i = 1; i <= n; i++) res ^= arr[i]; if (res) return true; else return false;
反尼姆博弈
题目一般是在n堆物品中,每人每次只能在一堆里面至少拿一个,无上限,当取完最后一个时该人失败。
计算所有堆中充裕堆的数目cnt(充裕堆指每堆的数量大于1),以及所有堆数量的异或ans;
如果 ans == 0 && cnt == 0 或者 ans != 0 && cnt != 0 先手必胜,否则后手必胜。
int cnt = 0; int ans = 0; for(int i=1;i<=n;i++){ ans ^= arr[i]; if (arr[i] > 1)cnt++; } if ((ans == 0 && cnt == 0) || (ans != 0 && cnt != 0))return true; else return false;