codeforces 455B A Lot of Games(博弈,字典树)

题目大意:给定n,表示字符串集合。给定k,表示进行了k次游戏,然后是n个字符串。每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手。

解题思路:首先对字符集合建立字典树,然后根据博弈的必胜必败性质搜索出先手的决策状态,可决定胜败3,只能胜利2,只能失败1,不可掌控(即对手可决定胜败)0。
对于状态3,为必胜,可以采用前K-1场败,然后保证第K场自己先手,取必胜方案。
对于状态2,无论则们走都是赢的话,肯定是两个人轮流胜局,所以判断K的奇偶性。
对于状态1和0,必败,因为一直输,一直先手。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn=1000010;
 8 
 9 struct Trie //字典树查询字符串
10 {
11     int ch[maxn][26];
12     int sz; //结点总数
13     void clear(){sz=1;memset(ch[0],-1,sizeof(ch[0]));}
14     int Num(char ch){ return ch-'a';}
15     void insert(char *s)
16     {
17         int len=strlen(s),u=0;
18         for(int i=0;i<len;i++)
19         {
20             int c=Num(s[i]);
21             if(ch[u][c]==-1)
22             {
23                 memset(ch[sz],-1,sizeof(ch[sz]));
24                 ch[u][c]=sz++;
25             }
26             u=ch[u][c];
27         }
28     }
29 }trie;
30 
31 int solve(int d)
32 {
33     int ans=0;
34     int flag=1;
35     for(int i=0;i<26;i++)
36     {
37         if(trie.ch[d][i] != -1)
38         {
39             flag=0;
40             ans|=solve(trie.ch[d][i]);
41         }
42     }
43     if(flag)
44         ans=1;
45     return 3-ans;
46 }
47 
48 int main()
49 {
50     int n,m;char s[maxn];
51     while(~scanf("%d%d",&n,&m))
52     {
53         trie.clear();
54         while(n--)
55         {
56             scanf("%s",s);trie.insert(s);
57         }
58         int ans = 3 - solve(0);
59         if(ans==3) printf("First\n");
60         else if(ans==1||ans==0) printf("Second\n");
61         else 
62         {
63             if(m&1) printf("First\n");
64             else printf("Second\n");
65         }
66     }
67     return 0;
68 }

 

posted on 2014-08-13 23:22  雄..  阅读(243)  评论(0编辑  收藏  举报

导航