Codeforces Round #260 (Div. 2) D

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;
}



你可能感兴趣的:(round,codeforces,D,字典树,#260)