博弈题目<四>
小花梨的取石子游戏
小花梨的取石子游戏
思路
我们发现,只要这一堆的石子大于1,那么这堆石子的掌控者就能通过控制取该堆的次数来掌握先机。因此特殊情况就是看看从该堆开始有几个1,比如说 1 1 1 2 2 ,开始有3个1,那么他们每个人只能一个一个拿,第三个1的时候就是先手把第三堆取走,然后后手就可以通过对2 进行直接取走或者是分开取来掌握全局。 因此我们需要记录从该点开始向后找的连续的1的个数,开始我是直接遍历,就超时了,后来想到可以从后往前遍历进行记录。用的时候直接查询就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <bits/stdc++.h> using namespace std; int a[300001]; int sum[300001]; int main() { int n; cin >> n; int flag = 0; for(int i = 0; i < n; ++i) { scanf("%d",&a[i]); if(a[i] != 1) flag = 1; a[n + i] = a[i]; } sum[n] = 0; for(int i = 2*n - 1; i >= 0; --i) { if(a[i] != 1) sum[i] = 0; else sum[i] = sum[i + 1] + 1; } if(n == 1) { for(int i = 0; i < n; ++i) { cout << "First" << '\n'; } } else if(!flag) { for(int i = 0; i < n; ++i) { if(n & 1) cout << "First" << '\n'; else cout << "Second" << '\n'; } } else{ for(int i = 0; i < n; ++i) { if(a[i] != 1) {cout << "First" << '\n'; continue;} if(sum[i] % 2) cout << "Second" << '\n'; else cout << "First" << '\n'; } } }
|
SDUT 3893
Return of the nim
思路
当N = 2时是威佐夫博弈,当N > 2是我们需要证明其是NIM博弈
1.当现在是平衡态,即异或和为0的时候,那么1可以执行操作1或者操作2打破平衡态,但是后手可以执行操作1就再次将其转化为平衡态。即假若现在是平衡态,先手必败
2.当现在是非平衡态,那么先手可以执行操作1将其转化为平衡态,即若开始平衡,先手必赢。
以上满足nim博弈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream> #include <algorithm> #include <string> #include <cstring> #include <math.h> using namespace std;
int main() { int t, a, b , n; cin >> t; while(t--) { cin >> n; if(n == 2) { cin >> a >> b; int num = int(((sqrt(5) + 1 )/ 2.0) * abs(b - a)); if(num != min(a,b)) cout << "Sherlock" << '\n'; else cout << "Watson" << '\n'; continue; } int f = 0; for(int i = 0; i < n; ++i) { cin >> a; f ^= a; } if(f) cout << "Sherlock" << '\n'; else cout << "Watson" << '\n'; } }
|