CF 260 DIV2 D. A Lot of Games(字典树+博弈)
2014-08-18 20:56
453 查看
题意:给你n个字符串,所有的字符串的长度加起来不超过10^5,两人来构造一个字符串,首先该字符串是为空,然后两人轮流选一个字母加在该字符串的尾部,要求两人构成的字符串是n个字符串中某个字符串的子串,没法继续选字母者败。 给你一个K,表示将该游戏进行K次,其中第一次游戏First先手,后面的k-1次的先手为第上次游戏的败者
例如,第一次First胜,则第二次游戏Second先手
求第K次游戏的胜者
方法:
将n个字符串存在字典树,然后遍历整棵树,其中每个结点状态的可能性有四种 1(表示改点必胜),2(表示改点必败),3(表示改点想败就败,想胜就胜),4(表示改点可能败,也可能胜,胜负由对手控制)
遍历树的过程时:
if(改点为树的叶子节点) ,改点状态为2 (因为无法再选择字母)
else if 某点的子节点中有状态为4的节点,则改点的状态为3 (因为只要在该点的人走到4,就可以控制对手的胜负,所有改点的状态为3)
当改点不是叶子节点且改点的字节点没有状态为4的点时:
if 改点的子节点有状态为1还有状态为2的子节点,则改点的状态为3(如果还有子节点有状态为3的节点,该点的状态也是3,因为只要该点不朝状态为3的点那边走即可)
else if 该点的子节点有状态为1且没有状态为2的子节点,则该点的状态为2 (如果还有子节点有状态为3的节点,该点也是必败,因为如果到达该点的人朝状态为3走,表示该
人该把想赢(想输的话走状态为1的子节点就可以了),但是朝3走之后,另一个人还是可以让他绝对输,所以该点状态为2)
else if 改点没有状态为1的点有状态为2的子节点,则改点的状态为1(理由同上)
else if 改点的子节点只有状态为3的子节点,改点的状态为4 (因为只要该点走到3,对手就能够想赢就赢,想输就输)
知道根节点的状态ans后进行判断:
若ans= 1,可得K把游戏中,First和Second两人轮流赢,则判断K的奇偶性就可知道第K把谁用
若ans= 2,可得K把游戏中,First每把都是先手,每把都输,则结果为Second胜
若ans=3,可得First第一把就可控制胜负,所有他只要一直控制K-1把让自己输,第K把赢即可
若ans=4, 可得胜负由对手控制,同上理可得,结果为Second胜
代码:
例如,第一次First胜,则第二次游戏Second先手
求第K次游戏的胜者
方法:
将n个字符串存在字典树,然后遍历整棵树,其中每个结点状态的可能性有四种 1(表示改点必胜),2(表示改点必败),3(表示改点想败就败,想胜就胜),4(表示改点可能败,也可能胜,胜负由对手控制)
遍历树的过程时:
if(改点为树的叶子节点) ,改点状态为2 (因为无法再选择字母)
else if 某点的子节点中有状态为4的节点,则改点的状态为3 (因为只要在该点的人走到4,就可以控制对手的胜负,所有改点的状态为3)
当改点不是叶子节点且改点的字节点没有状态为4的点时:
if 改点的子节点有状态为1还有状态为2的子节点,则改点的状态为3(如果还有子节点有状态为3的节点,该点的状态也是3,因为只要该点不朝状态为3的点那边走即可)
else if 该点的子节点有状态为1且没有状态为2的子节点,则该点的状态为2 (如果还有子节点有状态为3的节点,该点也是必败,因为如果到达该点的人朝状态为3走,表示该
人该把想赢(想输的话走状态为1的子节点就可以了),但是朝3走之后,另一个人还是可以让他绝对输,所以该点状态为2)
else if 改点没有状态为1的点有状态为2的子节点,则改点的状态为1(理由同上)
else if 改点的子节点只有状态为3的子节点,改点的状态为4 (因为只要该点走到3,对手就能够想赢就赢,想输就输)
知道根节点的状态ans后进行判断:
若ans= 1,可得K把游戏中,First和Second两人轮流赢,则判断K的奇偶性就可知道第K把谁用
若ans= 2,可得K把游戏中,First每把都是先手,每把都输,则结果为Second胜
若ans=3,可得First第一把就可控制胜负,所有他只要一直控制K-1把让自己输,第K把赢即可
若ans=4, 可得胜负由对手控制,同上理可得,结果为Second胜
代码:
#include <cstdio> #include <cstring> #define maxn 100005 int trie[maxn][27]; char ch[maxn]; int dfs(int n) { if(n== -1) return 1; int f1= 0, f2= 0, f3= 0, f4= 0; int sum= 0; for(int i= 1; i<= 26; i++) { if(trie [i]== -1)continue; sum++; int res= dfs(trie [i]); if(res== 1) f1= 1; else if(res== 2) f2= 1; else if(res== 3) f3= 1; else if(res== 4) f4= 1; } if(sum== 0) return 2; if(f4) return 3; if(f1) { if(f2) return 3;//可胜可负 else return 2; } else if(f2) return 1; else return 4; } int main() { int n, k; while(scanf("%d %d",&n,&k)!=EOF) { memset(trie, -1, sizeof(trie)); int tot= 0; //树中节点的个数 for(int i= 1; i<= n; i++) { scanf("%s",ch+1); int len= strlen(ch+1); int tt= 0; //当前的节点 for(int j= 1; j<= len; j++) { int k= ch[j]- 'a'+1; if(trie[tt][k]== -1) { trie[tt][k]= ++tot; tt= tot; } else tt= trie[tt][k]; } } int ans= dfs(0); if(ans== 1) { if(k&1) printf("First\n"); else printf("Second\n"); } else if(ans== 2 || ans== 4) printf("Second\n"); else if(ans== 3) printf("First\n"); } return 0; }
相关文章推荐
- Codeforces Round #260 (Div. 1) --B. A Lot of Games (Trie)
- Codeforces Round #260(Div2) Problem D. A Lot of Games
- Codeforces Round #260 (Div. 2) D. A Lot of Games
- CF 455B-- A Lot of Games
- A Lot of Games - CodeForces #260 (Div. 2) D Trie树
- CF 455B(A Lot of Games-树上博弈)
- codeforces content#260 D A Lot of Games
- Codeforces #260 (Div. 1) B. A Lot of Games(数据结构:trie+DFS)
- Codeforces Round #260 (Div. 1) B. A Lot of Games Trie + 博弈
- (CF) D. A Lot of Games
- Codeforces #260(Div 2) D A lot of games(字母树+树形dp)
- 【CF】310 Div.1 C. Case of Chocolate
- CF 题目集锦 PART 2 #260 div 1 C
- CodeForces 456D&455B--A Lot of Games(Trie+博弈)
- CF —— Codeforces Round #428 (Div. 2) B. Game of the Rows
- CF455B - A Lot of Games(Trie树+博弈)
- CF455B- A Lot of Games(Trie树+DFS+博弈)
- CF-Codeforces Round #418 (Div. 2)-C-An impassioned circulation of affection
- Codeforces 456 Problem D A Lot of Games
- A Lot of Games(Trie树 + 博弈)