hihocoder:博弈游戏·Nim游戏·二

来源:互联网 发布:淘宝店多少销量能靠前 编辑:程序博客网 时间:2024/06/06 03:03

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

Alice和Bob这一次准备玩一个关于硬币的游戏:
N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N。现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面)。翻最后一枚正面向上的硬币的人获胜。同样的,这次游戏里面Alice仍然先手,两人均采取最优的策略,对于给定的初始局面,Alice会获胜还是Bob会获胜?

输入

第1行:1个正整数N,表示硬币数量。1≤N≤10,000
第2行:1个字符串,第i个字符表示编号为i的硬币状态,’H’表示正面朝上,’T’表示背面朝上。

输出

第1行:1个字符串,若Alice能够获胜输出"Alice",否则输出"Bob"

样例输入
8HHTHTTHT
样例输出
Bob

题目里附带的提示已经说的很清楚了,关键是把如何这个问题转化为Nim游戏。

设所有硬币全部背面朝上的局面为局面0,第i枚硬币正面朝上的局面为局面i,局面i可以转化为局面0..i-1中的任意一种局面。

考虑把给定的局面拆成单个硬币的局面集合,比如给定了{HHTHTTHT},其中H表示正面朝上,T表示背面朝上。那么就是当前局面={局面1,局面2,局面4,局面7}。每一次我们可以改变其中个一个局面,当出现局面0时就从集合中删去。

若同时存在i,j(j<i)两枚硬币正面朝上。我们将这个局面拆成2个单一的局面:即局面i和局面j。
在反转i的时候我们考虑从局面i转移到局面j,那么我们会有两个局面j。
表示第j枚被反转了2次,也就是回到了背面朝上的状态。
那么我们得到这个游戏一个性质:当出现两个同样的局面时,等价于这两个局面合并变成了局面0。

而对于普通的Nim游戏,是不可能把两堆石子数一样的石堆同时取走的。

#include <iostream>#include <string>using namespace std;int main(){int n;cin >> n;int sum = 0;for (int i = 1; i <= n; i++){char p;cin >> p;if (p == 'H'){sum = sum^i;}}if (sum == 0)cout << "Bob" << endl;elsecout << "Alice" << endl;//system("pause");return 0;}




0 0