Codeforces 455B A Lot of Games(博弈)

http://codeforces.com/problemset/problem/455/B
B. A Lot of Games
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Andrew, Fedor and Alex are inventive guys. Now they invent the game with strings for two players.

Given a group of n non-empty strings. During the game two players build the word together, initially the word is empty. The players move in turns. On his step player must add a single letter in the end of the word, the resulting word must be prefix of at least one string from the group. A player loses if he cannot move.

Andrew and Alex decided to play this game k times. The player who is the loser of the i-th game makes the first move in the (i + 1)-th game. Guys decided that the winner of all games is the player who wins the last (k-th) game. Andrew and Alex already started the game. Fedor wants to know who wins the game if both players will play optimally. Help him.

Input

The first line contains two integers, n and k (1 ≤ n ≤ 1051 ≤ k ≤ 109).

Each of the next n lines contains a single non-empty string from the given group. The total length of all strings from the group doesn't exceed 105. Each string of the group consists only of lowercase English letters.

Output

If the player who moves first wins, print "First", otherwise print "Second" (without the quotes).

Sample test(s)
input
2 3
a
b
output
First
input
3 1
a
b
c
output
First
input
1 2
ab
output
Second
题意:给n个字符串(n<=100000)。两个人玩游戏,他们一起填一个字符串。一个人一个回合只能填一个字母。当某个人填完字母以后这个字符串不是n个字符串中某个字符串的前缀,那么那个人输。两个人一共玩K盘游戏,对于一盘游戏输的人做下一盘的先手。最后一盘游戏谁赢谁才是真正的赢家。两个人都采用最优策略,问是先手赢还是后手赢。(字符串的总长度不超过100000)
题解:首先我们要处理出对于一盘游戏先手能不能让自己赢,能不能让自己输。处理出来以后再分类讨论。假设一盘游戏中先手必输,那么先手最后一定输。假设先手只能赢,不能输,那么可以根据K的奇偶判断谁赢谁输。假设先手既能赢又能输,那么先手一定能赢。现在的问题是如何判断先手在一盘游戏中能不能赢,能不能输。由于字符串的总长度不超过100000,我们可以将字符串建字典树。对字典树进行dfs判断先手能否必赢,能否可输。这里我是分开处理的,进行了两次DFS。下面就说如何判断先手能否必赢。在搜索过程中,假设这个点是先手,他的下一个点是后手,那么只有该点下面所有的儿子都是先手必赢,那么这个点才能先手必赢,因为他的下一个点由后手控制,只有后手无论填那个点先手都要赢,这个点才能先手必赢。假设这个点是后手,下一个点由先手决定,那么该点只要有一个儿子是先手必赢,那么这个点就是先手必赢。判断先手是否可输同理。代码如下:
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#define mod 1000000007
#define inff 0x3fffffff
#define eps 1e-8
#define nn 110000
typedef long long LL;
const LL inf64=LL(inff)*inff;
using namespace std;
int n,k;
string s;
int num;
struct Trie
{
    int id;
    int next[30];
    void cs()
    {
        memset(next,-1,sizeof(next));
    }
}E[nn*10];
void init()
{
    E[0].cs();
    num=1;
}
void insert(string x)
{
    int i,l=x.size();
    int ix=0;
    for(i=0;i<l;i++)
    {
        if(E[ix].next[x[i]-'a']==-1)
        {
            E[ix].next[x[i]-'a']=num;
            E[num].id=x[i]-'a';
            E[num].cs();
            num++;
        }
        ix=E[ix].next[x[i]-'a'];
    }
}
bool dfs(int id,int len)
{
    int i;
    bool ix;
    for(i=0;i<26;i++)
    {
        if(E[id].next[i]!=-1)
        {
            ix=dfs(E[id].next[i],len+1);
            if(len%2==0&&ix)
                return true;
            if(len%2&&!ix)
                return false;
        }
    }
    if(len%2==0)
        return false;
    return true;
}
bool go(int id,int len)
{
    int i;
    bool ix;
    int fc=0;
    for(i=0;i<26;i++)
    {
        if(E[id].next[i]!=-1)
        {
            fc++;
            ix=go(E[id].next[i],len+1);
            if(len%2==0&&ix)
                return true;
            if(len%2&&!ix)
                return false;
        }
    }
    if(len%2==0&&fc==0)
        return true;
    if(len%2==1&&fc==0)
        return false;
    if(len%2==0)
        return false;
    return true;
}
int main()
{
    int i;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        init();
        for(i=1;i<=n;i++)
        {
            cin>>s;
            insert(s);
        }
        bool ans=dfs(0,0);
        bool ans1=go(0,0);
        if(!ans)
        {
            puts("Second");
        }
        else if(!ans1)
        {
            if(k%2)
                puts("First");
            else
                puts("Second");
        }
        else
        {
            puts("First");
        }
    }
    return 0;
}


你可能感兴趣的:(数据结构,ACM,DFS,博弈)