目录
巴什游戏与 P-position、N-position
巴什游戏
例题
有n颗石子,甲先取,乙后取,每次可以拿1~m颗石子,轮流拿,拿到最后一颗的人获胜。
输入:n和m,1<=n,m<=1000。
输出:如果先拿的甲赢了,输出"first",否则输出“second”。
分析
- 当n<=m时,由于一次最少拿1个,最多拿m个,所以一定是甲赢。
- n=m+1时,无论甲拿走多少个,乙一定能拿走剩下的全部,乙赢。
所以可以根据上面的情况扩展成下面两种情况:
- n%(m+1)==0时,甲不管拿多少个,例如k个,乙都拿走m+1-k,总是乙赢。
- n%(m+1)!=0,有余数r,那么,甲拿走r个,对于乙来说,就是上面那种情况的甲,总是甲赢。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n, m;
cin >> t;
while (t--) {
cin >> n >> m;
if (n % (m + 1))cout << "first\n";
else cout << "second\n";
}
return 0;
}
P-position、N-position与动态规划
例题
基础概念
P-position表示前一个玩家(即刚走过一步的玩家)的必胜位置,
N-position表示下一个玩家的必胜位置。
当前状态是N-position,则表示先手必胜,P-position表示先手必败。
题目分析
题目中说到,当前玩家无法移动硬币时,会输掉比赛
-
只有一个格子的时候
kiki先手,无法移动,所以先手必败
-
硬币可以往左移,往下移,往左下移,所以当n=1,m=2或n=2,m=1或n=2,m=2的情况来说,先手必胜。
-
这个情况可以继续向左,向下和向左下推广
从表中可以发现规律,当n和m都是奇数的时候,先手必败,否则先手必胜。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
while (cin >> n >> m, n + m) {
cout << ((n & 1 && m & 1) ? "What a pity!\n" : "Wonderful!\n");
}
return 0;
}
尼姆游戏
巴什游戏是只有一堆石头,而尼姆游戏是多堆石头。
结论
假设有n堆石头,数量分别是{a1, a2, a3, ……, an},两个玩家轮流拿石子,每次从任意一堆中拿出任意数量的石子,拿到最后一个石子的获胜
若a1 ^ a2 ^ a3 ^ … ^ an != 0 则先手必胜,为N-position
若a1 ^ a2 ^ a3 ^ … ^ an == 0 则先手必败,为P-position
^ 为异或运算。
例题
分析
基本原理就是使用尼姆游戏的结论,不过题目要求输出方案数,所以我们要进一步思考一下,在什么情况下算是一种方案?
假设有三堆石头,石子数量分别为5,7,9
它们的异或结果不为零,所以先手一定胜利。
根据上一小节动态规划的思想,我们可以假设,先手要创造一个让后手必败的局面,也就是说,先手从某一堆里拿出一部分石子后,让剩余几堆石子数量的异或结果为0。
比如,我们想在5中拿出去一些石子,然后让剩下的异或结果为0,但是我们发现,7和9异或后是14,我们怎么在5中取,都无法让5变成14 。
如果从7中取,我们发现,5和9异或结果是12,同样7也不能变成12
所以,我们试试从9中取。5和7的异或结果为2,这时,只要我们从9个石子中取出7个石子,剩下的石子异或结果就为0了,所以这是一个方案,结果为1 。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int m, a[110];
while (cin >> m, m) {
int sum = 0;
for (int i = 0; i < m; i++) {
cin >> a[i];
sum ^= a[i];
}
if (sum == 0)cout << "0\n";
else {
int cnt = 0;
for (int i = 0; i < m; i++) {
if ((sum ^ a[i]) <= a[i]) cnt++;
}
cout << cnt << '\n';
}
}
return 0;
}
图游戏与Sprague-Grundy函数
Sprague-Grundy函数是一种比用P-position和N-position分析更高级的分析方法,该方法利用图来作为分析工具。