描述
题解
哎,纳什真是给我出了一个难题啊~~~
博弈论简单的还能推算出来,稍微一难,我就陷入了懵逼死循环中……
这道题可以很清楚的分析到是Trie + 博弈
,首先建立Trie
树很容易,接着分析可以得到,先手拿到叶子节点的必赢,但是这个游戏一共需要进行k轮,并且第二轮开始每一轮的先手都是上一轮的败者,所以这个问题俨然变成了两个游戏,一个是尽全力输,一个是尽全力赢。剩下的也就好分析了,根据两人的必输和必赢的把握以及比赛轮数,推算出最后谁赢,这里需要注意可能有既不是必输也不是必赢的局面,需要看对手的仁慈了(又开始扯淡了……)。
代码
#include <iostream>
#include <cstring>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = 1e5 + 5;
const int MAXL = 26;
char s[MAXN];
int ch[MAXN][MAXL + 5];
int val[MAXN];
int sz;
int sg[MAXN];
void init()
{
sz = 1;
mem(ch[0], 0);
return ;
}
void inser(char *s)
{
int u = 0;
int len = (int)strlen(s);
for (int i = 0; i < len; i++)
{
int c = s[i] - 'a';
if (!ch[u][c])
{
mem(ch[sz], 0);
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = 1;
return ;
}
// 输
int losses(int u)
{
int x = 0, y = 0;
for (int j = 0; j < MAXL; j++)
{
int p = ch[u][j];
if (p)
{
if (losses(p))
{
x++;
}
else
{
y++;
}
}
}
if (x == 0 && y == 0)
{
return 1;
}
if (y)
{
return 1;
}
else
{
return 0;
}
}
// 赢
int gains(int u)
{
int x = 0, y = 0;
for (int j = 0; j < MAXL; j++)
{
int p = ch[u][j];
if (p)
{
if (gains(p))
{
x++;
}
else
{
y++;
}
}
}
if (y)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
init();
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
scanf("%s", s);
inser(s);
}
int A = losses(0); // A:1->先手可以达成必输,0->先手不可以达成必输
int B = gains(0); // B:1->先手可以达成必应,0->先手不可以达成必赢
if (A && B)
{
cout << "First" << endl;
}
else
{
if (A)
{
cout << "Second" << endl;
}
else
{
if (B)
{
if (k % 2)
{
cout << "First" << endl;
}
else
{
cout << "Second" << endl;
}
}
else
{
cout << "Second" << endl;
}
}
}
return 0;
}