您的位置:首页 > 其它

codeforces 455B A Lot of Games

2014-08-13 11:11 357 查看
今天终于把这题弄出来了。。。

前缀树+dfs+博弈。

博弈废伤不起,虽然一开始把正解想出来了,但是一琢磨就把自己弄懵了,没想明白的一点就是如果先手不能决定输赢,那么后手必定可以决定输赢。(越想越绕智商死完了。。有空得想办法拿笔证明一下。。)

1.先手有必胜和必输的两种选择的话就可以一直输到最后一局,很简单。

2.先手只有必输的选择的话,如果先手不选择必输的开头,那么后手可以选择让先手输

3.先手只有必胜的选择的话,那么后手可以决定先手的胜负,如果先手负有利于胜利,那么后手不会让先手负,如果先手胜有利于胜利,先手便选择胜利,因此两方都是一直胜下去,直到最后一局,k为奇先手胜,k为偶后手胜。

一直wa在第21组数据上,本来记录了叶子节点,把这个多余的记录去掉之后就过了,长记性。。以后没用的东西不要乱加。。

win[node]表示上一步选择了node之后,这一步的选择有没有必胜的可能,lose[node]同理,这样就不用纠结win[0]的问题了。

(scanf cout 混用大家无视掉。。太懒了。。)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int t[200005][26],n,k,size;
bool win[100005],lose[100005],visit[100005];
char s[100005];
void insert(char *s)
{
int node=0;
for(int i=0;i<strlen(s);i++)
{
int x=s[i]-'a';
if(!t[node][x]) t[node][x]=size++;
node=t[node][x];
}
return;
}
void dfs(int node)
{
int flag=0;
win[node]=lose[node]=0;
for(int i=0;i<=25;i++)
{
int son=t[node][i];
if(!son) continue;
if(!visit[son])
{
dfs(son);
visit[son]=1;
}
flag=1;
if(!win[son])win[node]=1;
if(!lose[son])lose[node]=1;
}
if(!flag) lose[node]=1;
return;
}
void init()
{
memset(t,0,sizeof(t));
memset(win,0,sizeof(win));
memset(lose,0,sizeof(lose));
memset(visit,0,sizeof(visit));
size=1;
return;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
init();
for(int i=0;i<=n-1;i++)
{
scanf("%s",s);
insert(s);
}
dfs(0);
if(win[0]&&(lose[0]||(k&1)))
{
cout<<"First"<<endl;
continue;
}
cout<<"Second"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: