codeforces 455B A Lot of Games

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

前缀树+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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值