hy 的惩罚
【问题描述】
hy 抄题解又被老师抓住了,现在老师把他叫到了办公室。 老师要 hy 和他 玩一个游戏。如果 hy 输了,老师就要把他开除信息组; 游戏分为 k 轮。在游戏开始之前,老师会将 n 个由英文字母组成的字符串放 入箱子。
每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字 符串为箱子中某字符串的前缀,直到有一个人不能操作,不能操作的那个人就输 掉当前的一轮。新一轮由上一句输的人先手。最后一局赢的人获胜。
假定老师和 hy 都能采取最优的策略,且老师为了彰显自己的大度让 hy 先手, 求 hy 能否获胜。
【输入格式】 输入包括多组数据,输入以文字流结尾(EOF)为结束。 每组数据的第一行包含两个整数 n, k,分别表示放入箱子字符串的数量和游 戏的轮数。 接下来 n 行,每行一个字符串表示由英文字母组成的句子。
【输出格式】 每组数据第一行,输出 hy 是否能赢,若能赢输出”HY wins!“,否则输出” Teacher wins!”。
【样例输入 1】 2 3
a b
3 1
a b c
【样例输出 1】 HY wins!
HY wins!
【样例输入 2】 1 2
ab
【样例输出 2】 Teacher wins!
全国信息学奥林匹克联赛(NOIP2017)模拟赛 提高组
【评测用例规模与约定】 对于 40%的评测用例,1≤n≤10,1≤k≤10 4; 对于 100%的评测用例,1≤n≤10 5,1≤k≤10 9,保证所有字符串总长度不超过 10 5, 数据组数不超过 10
题解:
博弈论+递推+字典树
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int num,ch[100001][28],n,k; 7 bool f[100001][3],p,p2; 8 char s[200001]; 9 void build() 10 {int len,x,i; 11 len=strlen(s); 12 x=0; 13 for (i=0;i<len;i++) 14 if (ch[x][s[i]-'a']==0) 15 { 16 num++; 17 ch[x][s[i]-'a']=num; 18 x=num; 19 } 20 else x=ch[x][s[i]-'a']; 21 } 22 bool dfs(int x,bool y,bool z) 23 {int i,k1=0,k2=0; 24 for (i=0;i<26;i++) 25 if (ch[x][i]) 26 { 27 if (x) 28 dfs(ch[x][i],!y,z); 29 else dfs(ch[x][i],y,z); 30 } 31 for (i=0;i<26;i++) 32 if (ch[x][i]) 33 { 34 if (x==0) 35 { 36 if (f[ch[x][i]][y]) 37 k1++; 38 else k2++; 39 } 40 if (x!=0) 41 { 42 if (f[ch[x][i]][!y]) 43 k1++; 44 else k2++; 45 } 46 } 47 if (x==0&&y==1&&k1!=0) 48 { 49 if (k2==0) p=0; 50 else p=1; 51 } 52 if (x==0&&y==1) 53 { 54 if (k1!=0) return 1; 55 else return 0; 56 } 57 if (x==0&&y==0) 58 { 59 if (k2!=0) return 0; 60 else return 1; 61 } 62 if (k1==0&&k2==0) 63 { 64 if (y==1) p=1; 65 f[x][y]=y; 66 return y; 67 } 68 if (y==1&&k2!=0) 69 { 70 f[x][y]=0; 71 return 0; 72 } 73 if (y==0&&k1==0) 74 { 75 f[x][y]=0; 76 return 0; 77 } 78 if (y==1&&k2==0) 79 { 80 f[x][y]=1; 81 return 1; 82 } 83 if (y==0&&k1!=0) 84 { 85 if (k2!=0) p=1; 86 f[x][y]=1; 87 return 1; 88 } 89 } 90 int main() 91 {int i,j; 92 bool b1,b2; 93 freopen("amerce.in","r",stdin); 94 freopen("amerce.out","w",stdout); 95 while (cin>>n>>k) 96 { 97 memset(ch,0,sizeof(ch)); 98 num=0; 99 memset(f,0,sizeof(f)); 100 p=0; 101 for (i=1;i<=n;i++) 102 { 103 scanf("%s",s); 104 build(); 105 } 106 b1=dfs(0,1,1);//先手 107 b2=dfs(0,0,0);//后手 108 //cout<<b1<<' '<<b2<<endl; 109 if (b1&&b2) printf("HY wins!\n"); 110 if (b1&&!b2) 111 { 112 if (k%2==0) 113 { 114 if (p==0) 115 printf("Teacher wins!\n"); 116 else printf("HY wins!\n"); 117 } 118 if (k%2==1) printf("HY wins!\n"); 119 } 120 if (!b1&&b2) 121 { 122 printf("Teacher wins!\n"); 123 } 124 if (!b1&&!b2) printf("Teacher wins!\n"); 125 } 126 }