25.集合-Nim游戏 博弈论

 

 

 

 SG(x) = 0,必败

SG(x) != 0,必胜

如果是多张图的话

 石子堆数是10000,所以一共是10000个状态,枚举集合的个数是100

时间复杂度就是1e6

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 110, M = 10010;
 4 int n, k;
 5 int s[N], f[M];
 6 //s存储给出的各个数
 7 //f存储每堆石子的sg的值
 8 int sg(int x) { 
 9     if (f[x] != -1) { //如果已经被算过了,不继续计算了,直接返回
10         return f[x];
11     }
12     unordered_set<int> S; //存储当前这个局面能到的所有局面
13     for (int i = 0; i < k; i++) { 
14         int sum = s[i]; //现在sum[i]就是集合中的数,也就是可以取出的石子数
15         if (x >= sum) {
16             S.insert(sg(x - sum));
17         }
18     }
19     for (int i = 0; ; i++) { //找到集合当中不存在的最小的自然数是多少
20         if (!S.count(i)) {
21             return f[x] = i;
22         }
23     }
24 }
25 int main() {
26     cin >> k;
27     for (int i = 0; i < k; i++) {
28         cin >> s[i];
29     }
30     cin >> n;
31     memset(f, -1, sizeof f); //用记忆化搜索来做
32     int res = 0;
33     for (int i = 0; i < n; i++) {
34         int x;
35         cin >> x;
36         res ^= sg(x);
37     }
38     if (res) {
39         cout << "Yes" << endl;
40     } else {
41         cout << "No" << endl;
42     }
43     return 0;
44 }

 

posted @ 2020-08-21 11:25  kyk333  阅读(200)  评论(0)    收藏  举报