练习赛 Alice and Bob 博弈论
Alice and Bob
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 23 Accepted Submission(s) : 6
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
二人玩游戏,轮流进行,Alice先行。游戏是这样的,排成一行的N个硬币,有些正面朝上,有些反面朝上。每一次玩家都可以把任意S个连续的硬币翻转(1<=S<=N),但是必须保证S个硬币中最右边的那个必须是从正面到反面。不能进行的玩家输掉游戏。 假定两人采用最优策略,Alice能赢吗?
Input
第一行是整数T(1 <=T <= 100) - 测试实例的数目. 每个测试实例仅一行,长度在3 至15之间的字符串,表示游戏的开始状态,字符是 'H'(正面)或 'T' (反面).
Output
针对每一个实例,Alice能赢,输出YES,否则NO
Sample Input
3 TTTT HTHT HTTH
Sample Output
NO NO YES
Author
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <vector> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 using namespace std; 11 #define maxn 101 12 #define mod 1000000007 13 #define INF 0x7fffffff 14 //#define ll long long 15 #define ll __int64 16 char str[maxn]; 17 int a[maxn]; 18 int vis[maxn]; 19 int n,m; 20 map<ll,int>sg; 21 ll fun(ll x,int l,int r){ 22 for(int i=l;i<=r;i++) 23 if(x&((ll)1<<i))x=x-((ll)1<<i); 24 else x=x+((ll)1<<i); 25 return x; 26 } 27 void SG(){ 28 sg[0]=0; 29 for(ll i=1;i<((ll)(1<<n));i++){ 30 memset(vis,0,sizeof vis); 31 for(int j=0;j<n;j++) 32 if(i&((ll)1<<j)) 33 for(int k=j;k>=0;k--){ 34 ll x=fun(i,k,j); 35 vis[sg[x]]=1; 36 } 37 for(int j=0;;j++)if(!vis[j]){ 38 sg[i]=j; 39 break; 40 } 41 } 42 } 43 int main(){ 44 int t; 45 scanf("%d",&t); 46 while(t--){ 47 sg.clear(); 48 scanf("%s",str); 49 n=strlen(str); 50 memset(a,0,sizeof 0); 51 ll x=0; 52 for(int i=0;i<n;i++)if(str[i]=='H'){a[n-i-1]=1;x|=((ll)1<<i);} 53 SG(); 54 if(sg[x])printf("YES\n"); 55 else printf("NO\n"); 56 } 57 return 0; 58 }
View Code 2013-09-25 17:23:17
浙公网安备 33010602011771号