• 【Foreign】Game [博弈论][DP]


    Game

    Time Limit: 20 Sec  Memory Limit: 512 MB

    Description

      从前有个游戏。游戏分为 k 轮。

      给定一个由小写英文字母组成的字符串的集合 S,

      在每轮游戏开始时,双方会得到一个空的字符串,

      然后两人轮流在该串的末尾添加字符,并且需要保证新的字符串是 S 中某个串的前缀,直到有一方不能操作,则不能操作的一方输掉这一轮。

      新的一轮由上一轮输的人先手,最后一轮赢的人获得游戏胜利。

      假定双方都采取最优策略,求第一轮先手的一方能否获胜。

    Input

      输入包含多组数据。

      每组数据的第一行包含两个整数 n,k,分别表示字符串的数量和游戏的轮数。

      接下来 n 行,每行一个由小写英文字母组成的字符串。

    Output

      对于每组数据输出一行,若先手能获胜输出 HY wins!,否则输出 Teacher wins!

    Sample Input

      2 3
      a
      b
      3 1
      a
      b
      c

    Sample Output

      HY wins!
      HY wins!

    HINT

      1 ≤ n ≤ 1e5,1 ≤ k ≤ 1e9,保证所有字符串长度不超过 1e5,数据组数不超过 10。

    Solution

      

       显然Trie上这个DP显然就是为了求:一轮中,先手是否必胜或者必败。显然,一个点如果可以走向必败点那么就可以必胜

    Code

     1 #include<iostream>    
     2 #include<string>    
     3 #include<algorithm>    
     4 #include<cstdio>    
     5 #include<cstring>    
     6 #include<cstdlib>
     7 #include<cmath>
     8 using namespace std;  
     9 typedef long long s64;
    10 typedef unsigned int u32;
    11  
    12 const int ONE = 1e6 + 5;
    13 
    14 int n, k;
    15 char s[ONE];
    16 int next[ONE][27], total, root = 1;
    17 int f[ONE], g[ONE];
    18 
    19 int get()
    20 {    
    21         int res=1,Q=1;char c;    
    22         while( (c=getchar())<48 || c>57 ) 
    23         if(c=='-')Q=-1; 
    24         res=c-48;     
    25         while( (c=getchar())>=48 && c<=57 )    
    26         res=res*10+c-48;
    27         return res*Q;
    28 }
    29 
    30 void Insert()
    31 {
    32         scanf("%s", s + 1);
    33         int u = root, n = strlen(s + 1);
    34         for(int i = 1; i <= n; i++)
    35         {
    36             int c = s[i] - 'a' + 1;
    37             if(!next[u][c]) next[u][c] = ++total;
    38             u = next[u][c];
    39         }
    40 }
    41 
    42 void Dfs_f(int u)
    43 {
    44         if(!u) return;
    45         int PD = 1; 
    46         for(int c = 1; c <= 26; c++) if(next[u][c]) {PD = 0; break;}
    47         if(PD) {g[u] = 0; return;}
    48         
    49         PD = 0;
    50         for(int c = 1; c <= 26; c++)
    51         {
    52             Dfs_f(next[u][c]);
    53             if(next[u][c] && f[next[u][c]] == 0) PD = 1;
    54         }
    55         f[u] = PD;
    56 }
    57 
    58 void Dfs_g(int u)
    59 {
    60         if(!u) return;
    61         int PD = 1; 
    62         for(int c = 1; c <= 26; c++) if(next[u][c]) {PD = 0; break;}
    63         if(PD) {g[u] = 1; return;}
    64         
    65         PD = 0;
    66         for(int c = 1; c <= 26; c++)
    67         {
    68             Dfs_g(next[u][c]);
    69             if(next[u][c] && g[next[u][c]] == 0) PD = 1;
    70         }
    71         g[u] = PD;
    72 }
    73 
    74 int main()
    75 {
    76         while(scanf("%d %d", &n, &k) != EOF)
    77         {
    78             memset(f, 0, sizeof(f));
    79             memset(g, 0, sizeof(g));
    80             memset(next, 0, sizeof(next));
    81             total = 1;
    82             for(int i = 1; i <= n; i++)
    83                 Insert();
    84             Dfs_f(1);    Dfs_g(1);
    85             if(f[1] == 1 && g[1] == 1) printf("HY wins!
    ");
    86             else
    87             if(f[1] == 1)
    88                 k % 2 == 1 ? printf("HY wins!
    ") : printf("Teacher wins!
    ");
    89             else
    90                 printf("Teacher wins!
    ");
    91         }
    92 }
    View Code

     

  • 相关阅读:
    网页连接无法打开可运行
    SET XACT_ABORT
    用Windows Live Writer写CSDN博客的步骤
    ATO,PTO
    什么是贸易顺差?
    ATO/MTO类机械制造业特点以及ERP需求分析(二)
    如何在早期版本的 Office 中打开并保存 Word 2007、Excel 2007 和 PowerPoint 2007 文件
    Alpha和Beta测试简介
    IIS6.0下 Asp网页访问出现500的问题
    合格的程序员
  • 原文地址:https://www.cnblogs.com/BearChild/p/7617861.html
Copyright © 2020-2023  润新知