codeforces 455B A Lot of Games

来源:互联网 发布:网络的利与弊论文1000 编辑:程序博客网 时间:2024/05/29 03:23

今天终于把这题弄出来了。。。

前缀树+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;}


0 0
原创粉丝点击