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 }

 

posted @ 2017-07-13 20:48  Z-Y-Y-S  阅读(661)  评论(0编辑  收藏  举报