D. A Lot of Games
题意:博弈问题。两个人玩游戏。有n个字符串,两个人轮流往一个空串word里添加字母,每次添加后word必须是这n个字符串中某个(些)串的前缀。无法添加字母的一方输。然后他们要连续玩k次这个游戏,每次输的一方下一次游戏先行动。最后的那次游戏胜利才是最终的胜利。问开始先行动能赢还是后行动能赢。
思路:字典树存串。然后遍历树来找先行动是否有必胜和必败策略。判断必胜如果有一条路能赢就是赢,否则输。判断必败同理。然后到底谁赢要将是否有必胜/必败策略和游戏次数结合起来判断。
第一次写字典树,看着概念自己YY写的居然A了。。这个故事告诉我们,有些游戏里有必胜策略不一定有必败策略,有必败策略不一定有必胜策略,但是两者至少有其一。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000
#define ll long long
#define min3(a,b,c) min(a,min(b,c))
using namespace std;
struct node{
char c;
node* next[26];
};
void _insert(node* r,char* str,int len){
node* cur=r;
for(int i=0;i<len;i++){
if(cur->next[str[i]-97]==0){
cur->next[str[i]-97]=new node();
cur->next[str[i]-97]->c=str[i];
}
cur=cur->next[str[i]-97];
}
}
bool win(node* r){
bool isnull=true;
for(int i=0;i<26;i++){
if(r->next[i]!=0)isnull=false;
}
//无路可走就输了
if(isnull)return false;
for(int i=0;i<26;i++){
if(r->next[i]==0)continue;
if(!win(r->next[i]))return true;//能让别人无路可走就赢了
}
//无法让别人无路可走就输了
return false;
}
bool lose(node* r){
bool isnull=true;
for(int i=0;i<26;i++){
if(r->next[i]!=0)isnull=false;
}
if(isnull)return true;
for(int i=0;i<26;i++){
if(r->next[i]==0)continue;
if(!lose(r->next[i]))return true;
}
return false;
}
int main(){
int n,k;
while(cin>>n>>k){
node* root=new node();
char str[100010];
for(int i=1;i<=n;i++){
cin>>str;
_insert(root,str,strlen(str));
}
if(k&1){
if(win(root)){
cout<<"First"<<endl;
}else{
cout<<"Second"<<endl;
}
}else{
if(win(root)&&lose(root)){
cout<<"First"<<endl;
}else{
cout<<"Second"<<endl;
}
}
}
return 0;
}