hiho一下 第四十五周 博弈游戏·Nim游戏·二(转成NIm)
Alice和Bob这一次准备玩一个关于硬币的游戏:
N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N。现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面)。翻最后一枚正面向上的硬币的人获胜。同样的,这次游戏里面Alice仍然先手,两人均采取最优的策略,对于给定的初始局面,Alice会获胜还是Bob会获胜?
题意:
要使得所有硬币背面向上。每次只能反转一个正面向上的硬币到背面向上,同时可选择对该位置左边的其中一个硬币进行反转。
思路:
官网已经很详细说明解法,但是思路可能不是很顺,多看几遍应该就行了。主要就是(1)拆成单个正面的情况,转成Nim(2)考虑是否会有与Nim规则冲突的地方。
关于赢家如何维持必赢局面?
无论对方取走多少石子,赢家只要取走同数量的石子即可,即”抵消“!因为两者的异或结果为0。若是在刚开局时,对方并还没有行动过,那么赢家可以取走一堆比较特殊的石子,只要使得其他的异或结果为0就保持了每次留赢的局面给自己。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=11000; 4 int a[N]; 5 int main() 6 { 7 //freopen("input.txt","r",stdin); 8 int n; 9 string s; 10 while(cin>>n) 11 { 12 cin>>s; 13 int j=0; 14 for(int i=0; i<n; i++) //拆成单个正面情况 15 { 16 if(s[i]=='H') 17 a[j++]=i+1; 18 } 19 for(int i=1; i<j; i++)//异或,计算结果 20 a[0]^=a[i]; 21 if(a[0])//不为0 22 cout<<"Alice"<<endl; 23 else 24 cout<<"Bob"<<endl; 25 } 26 return 0; 27 }