题意:有n个字符串,玩k次游戏,每次每个人添加一个小写字母于字符串屁股后,此字符串必须是给出n个字符串之一的前缀,玩不下去的算输。此为一次游戏局面的输赢,这次输的下次先手。为先手能不能保证第k次能赢。
题解:假设此游戏有两种局面,可赢,可输。如果先手确定不能赢,不管怎么样都赢不了了。如果先手能赢能输,那么可以前面一直输输输,保证先手,然后到第k局再爆发,赢了!如果先手只有赢的局面,那么就得看k是奇数或者偶数了。好了。现在的问题就变成怎么样知道这个局面的先手输赢。在这里我看了别人大神的代码。先把字符串状态存起来,然后根据博弈思想DP求得先手的输赢情况。具体参详。。。或者用字典树也可以求出来。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
#define LL __int64
char s[100010];
int dp[200010][30];
int win[200010],lose[200010];
int main()
{
int n,k,i,j,m,t;
scanf("%d%d",&n,&k);
getchar();
m=0;
memset(dp,0,sizeof(dp));
for (i=0;i<n;i++)
{
gets(s);
t=0;
int l=strlen(s);
for (j=0;j<l;j++)
{
int p=s[j]-'a';
if (dp[t][p]==0)
dp[t][p]=++m;
t=dp[t][p];
}
}
memset(win,0,sizeof(win));
memset(lose,0,sizeof(lose));
for (i=m;i>=0;i--)
{
int f=1;
for (j=0;j<26;j++)
if (dp[i][j])
{
f=0;
break;
}
if (f)
{
win[i]=0;
lose[i]=1;
continue;
}
for (j=0;j<26;j++)
if (dp[i][j])
{
if (!win[dp[i][j]])
win[i]=1;
if (!lose[dp[i][j]])
lose[i]=1;
}
}
if (!win[0])
puts("Second");
else if (lose[0])
puts("First");
else
{
// 只能赢。
if (k % 2==1) puts("First");
else puts("Second");
}
return 0;
}