CF456D A Lot of Games (字典树+DP)
CF#260 Div2 D题
CF#260 Div1 B题
Codeforces Round #260
CF455B
|
D. A Lot of Games
time limit per test
1 second memory limit per test
256 megabytes input
standard input output
standard output Andrew, Fedor and Alex are inventive guys. Now they invent the game with strings for two players. Given a group of n non-empty strings. During the game two players build the word together, initially the word is empty. The players move in turns. On his step player must add a single letter in the end of the word, the resulting word must be prefix of at least one string from the group. A player loses if he cannot move. Andrew and Alex decided to play this game k times. The player who is the loser of the i-th game makes the first move in the (i + 1)-th game. Guys decided that the winner of all games is the player who wins the last (k-th) game. Andrew and Alex already started the game. Fedor wants to know who wins the game if both players will play optimally. Help him. Input
The first line contains two integers, n and k (1 ≤ n ≤ 105; 1 ≤ k ≤ 109). Each of the next n lines contains a single non-empty string from the given group. The total length of all strings from the group doesn't exceed 105. Each string of the group consists only of lowercase English letters. Output
If the player who moves first wins, print "First", otherwise print "Second" (without the quotes). Sample test(s)
Input
2 3 Output
First Input
3 1 Output
First Input
1 2 Output
Second |
题意:两个人玩游戏。游戏是拼单词,给出了一个含有n个单词的词库。当前单词初始为空,每个人轮流给它末尾加一个字母,要求当前单词是词库中任意一个词的前缀,当某个人不能加字母了他就输。这个游戏重复k局,一局输的人下一局先手,最后一局定胜负。两个人都不蠢,求第一局先手是否能保证最后能赢,能就输出First,不能则输出Second。
题解:
Trie树+树DP。
先把词典各词加入Trie树,则Trie树每个节点都为游戏中的某一步,游戏就变成从这棵树树根开始轮流向下走一步,看谁能走到叶子。
这样,每个节点可能有4种状态,分别是必赢、必输、能输能赢(想怎样就怎样)、不能输不能赢(走这步会让对面变得能输能赢)。
叶子节点都是必赢。只有一个必赢儿子的点必输,只有一个必输儿子的点必赢。接下来我们主要考察有多个儿子的特殊情况。
我们可以统计儿子有哪些种类,即统计儿子中是否有能输能赢点、不能输不能赢点、必输点、必赢点,
1.若儿子中有能输能赢点,则对手肯定怒走那个点,则当前这个点是不能输不能赢点。
2.若儿子中又有赢点又有输点,对手可以随便选,则当前这个点也是不能输不能赢点。
3.若儿子中只有不能输不能赢点,则对手只能走这个逗点,则当前这个点是能输能赢点。
4.若儿子只有赢点,当前点肯定是输点;若儿子只有输点,当前点肯定是赢点。
这样,我们一遍dfs就可以得到所有点的状态,简直树DP。
最后简单判断一下到底第一局先手能不能赢。
1.假如每局先手能输能赢,则第一局先手的人可以连输k-1场,保证先手权,最后一场赢。
2.假如每局先手必赢,则后手必输,先手想输也输不掉,这样两个人轮流赢,若k是奇数,则第一局先手的人最后一局赢。
3.除了这些情况之外,先手都不能必赢。
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usint unsigned int
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) printf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1biao.out","w",stdout) const int maxn=;
int n,k;
char s[maxn];
int chd[maxn][];
int canwin[maxn],canlose[maxn];
int tn;
int ID[]; void insert(char *s) {
int len=strlen(s),i;
int now=;
for(i=; i<len; i++) {
if(!chd[now][ID[s[i]]]) chd[now][ID[s[i]]]=tn , now=tn++;
else now=chd[now][ID[s[i]]];
}
} void dfs(int x) {
int i;
bool last=true;
bool cwin=,close=,canwinlose=,cant=;
for(i=; i<; i++) {
if(chd[x][i]!=) {
//printf("%c:",'a'+i);
dfs(chd[x][i]);
last=false;
if(canwin[chd[x][i]]){///统计儿子有4种点中的哪些点
if(canlose[chd[x][i]])canwinlose=;
else cwin=;
}
else {
if(canlose[chd[x][i]]) close=;
else cant=;
}
}
}
canwin[x]=;canlose[x]=;///初始化为0,0
if(last)canwin[x]=;
else{
if(canwinlose==){///如果儿子里有有能赢又能输的点,当前点肯定是0,0,没有这种点才继续看
if(!(cwin && close)){///如果儿子里又有赢点又有输点,当前点肯定是0,0,不是这种情况才继续看
if(cant && !cwin && !close)///如果儿子只有0,0点,当前点肯定是1,1点
canwin[x]=,canlose[x]=;
else if(cwin)///如果儿子只有赢点,当前点肯定是输点
canlose[x]=;
else if(close)///儿子只有输点,当前点肯定是赢点
canwin[x]=;
}
}
}
//printf("(%d,%d)",canwin[x],canlose[x]);
} int main() {
int i,j;
REP(i,) {
ID[i+'a']=i;
}
while(scanf("%d%d",&n,&k)!=EOF) {
mz(chd);
tn=;
for(i=; i<n; i++) {
scanf("%s",s);
insert(s);
}
canwin[]=;canlose[]=;
for(i=; i<; i++) {///众起点中有赢点,走这个点就必赢;有输点,走这个点就必输。
if(chd[][i]!=) {
dfs(chd[][i]);
if(canwin[chd[][i]])canwin[]=;
if(canlose[chd[][i]])canlose[]=;
//printf("%c,%d,%d\n",'a'+i,canwin[chd[0][i]],canlose[chd[0][i]]);
}
}
//printf("%d,%d\n",canwin[0],canlose[0]);
bool first=false;
if(canwin[])
if(canlose[]) first=true;///能输能赢,乃真正法器(连输,最后赢一局)
else if((k&)==)first=true;///能赢不能输,则必轮流赢
///其他情况不能必赢
if(first)puts("First");
else puts("Second");
}
return ;
}
CF456D A Lot of Games (字典树+DP)的更多相关文章
- Manthan, Codefest 16 C. Spy Syndrome 2 字典树 + dp
C. Spy Syndrome 2 题目连接: http://www.codeforces.com/contest/633/problem/C Description After observing ...
- UVALive 3942 Remember the Word 字典树+dp
/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...
- LA 3942 - Remember the Word (字典树 + dp)
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...
- HDU5715 XOR 游戏 二分+字典树+dp
当时Astar复赛的时候只做出1题,赛后补题(很长时间后才补,懒真是要命),发现这是第二简单的 分析: 这个题,可以每次二分区间的最小异或和 进行check的时候用dp进行判断,dp[i][j]代表前 ...
- Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)
E. Ann and Half-Palindrome time limit per test 1.5 seconds memory limit per test 512 megabytes input ...
- Codeforces 455B A Lot of Games(字典树+博弈)
题目连接: Codeforces 455B A Lot of Games 题目大意:给定n.表示字符串集合. 给定k,表示进行了k次游戏,然后是n个字符串.每局開始.字符串为空串,然后两人轮流在末尾追 ...
- BZOJ 4260 Codechef REBXOR (区间异或和最值) (01字典树+DP)
<题目链接> 题目大意:给定一个序列,现在求出两段不相交的区间异或和的最大值. 解题分析: 区间异或问题首先想到01字典树.利用前缀.后缀建树,并且利用异或的性质,相同的两个数异或变成0, ...
- UVALive 3942 字典树+dp
其实主要是想学一下字典树的写法,但这个题目又涉及到了DP:这个题目要求某些单词组成一个长子串的各种组合总数,数据量大,单纯枚举复杂度高,首先肯定是要把各个单词给建成字典树,但是之后该怎么推一时没想到. ...
- LA 3942 - Remember the Word 字典树+DP
看题传送门:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...
随机推荐
- 【BZOJ-1926】粟粟的书架 二分 + 前缀和 + 主席树
1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MBSubmit: 616 Solved: 238[Submit][Statu ...
- 心血来潮学python
第一次见python就被吸引了,嗯,前面在linux下调试过一些小段代码.最近工作都在windows下面,也懒得换去unbuntu,所以想着在win下安装python. 之前不知道用什么方法装的pyt ...
- 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表
一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...
- WCF入门
一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...
- jQuery中的text()、html()和val()以及innerText、innerHTML和value
*jQuery中设置或者获取所选内容的值:text();设置或者获取所选元素的文本内容: html();设置或者获取所选元素的内容(包括html标记): val();设置或者获取表单字段的值(前提是表 ...
- 系统配置 之:远程桌面连接(win7系统)
本文包括两部分: 1.配置远程桌面连接 2.解决[远程桌面连接不上] 一.远程桌面连接设置 [远程桌面连接配置] Win7系统下的远程桌面连接设置,如果是其他系统或 Win8 及其以上系统,也可作为参 ...
- 循序渐进 Jprofiler
一 Jprofiler 1 什么是Jprofiler JProfiler是一个全功能的Java剖析工具(profiler),专用于分析J2SE和J2EE应用程式.它把CPU.线程和内存的剖析组合在一个 ...
- iOS内存管理个人总结
一.变量,本质代表一段可以操作的内存,她使用方式无非就是内存符号化+数据类型 1.保存变量有三个区域: 1>静态存储区 2>stack 3>heap 2.变量又根据声明的位置有两种称 ...
- BZOJ1915: [Usaco2010 Open]奶牛的跳格子游戏
权限题,没有传送门. 这很显然是一道DP题,刚看完题目可能会比较懵逼.这道题如果不要求回去,那么就是一道很裸的DP题.但是本题要求回去而且回去的格子的前一个格必须是之前经过的. 先不考虑回去的路程,对 ...
- POJ1426 Find The Multiple (宽搜思想)
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24768 Accepted: 102 ...