[AcWing] 894. 拆分-Nim游戏(C++实现)博弈论SG函数例题
1. 题目
2. 读题(需要重点注意的东西)
思路:
首先要知道几个定义
公平组合游戏(ICG)
必胜状态和必败状态
SG函数
mex运算
有向图游戏的和
SG值的意义
SG值的一个定理
本题思路:
本题的主要思路就是代结论,求出每个局面的SG值,但是需要注意,此题的局面有很多种,因为一堆石子(如上图a1)又可以分为两堆石子(如上图(b1,b2)、(c1,c2)),考虑所有的局面,用mex运算计算出sg值,然后代入结论:
3. 解法
---------------------------------------------------解法---------------------------------------------------
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 110;
int n;
int f[N];
int sg(int x)
{
if (f[x] != -1) return f[x]; // 记忆化搜索
unordered_set<int> S; // 用哈希表来存储
// 当前状态可以变为如下局面
for (int i = 0; i < x; i ++ )
for (int j = 0; j <= i; j ++ )
// 存储分出来的两堆石子sg值的异或
S.insert(sg(i) ^ sg(j));
for (int i = 0;; i ++ ) // mex运算求出该堆石子的sg值
if (!S.count(i))
return f[x] = i;
}
int main()
{
cin >> n;
memset(f, -1, sizeof f);
int res = 0;
while (n -- )
{
int x;
cin >> x;
res ^= sg(x); // 公式
}
if (res) puts("Yes");
else puts("No");
return 0;
}
可能存在的问题
4. 可能有帮助的前置习题
- [AcWing] 893. 集合-Nim游戏(C++实现)博弈论SG函数模板题
5. 所用到的数据结构与算法思想
- 博弈论
- SG函数
- 记忆化搜索
6. 总结
博弈论SG函数例题,理解思想并自己实现代码。