首页 > 代码库 > codeforces 456d (字典树+DP)

codeforces 456d (字典树+DP)

题目大意:给定n,表示字符串集合。给定k,表示进行了k次游戏,然后是n个字符串。每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手。

思路:00 代表不能控制 01代表败,10代表胜,11代表能输能赢

转自  http://blog.csdn.net/blankcqk/article/details/38459033

附带字典树模版:

void insert(){    int len = strlen(s);    int now = root;    for(int i = 0;i < len;i++){        int tmp = s[i] - a + 0;        if(!q[now][tmp]) q[now][tmp] = ++top;        now = q[now][tmp];    }}其中root为初始值加入所得的序号根据加入的顺序得来 

AC代码:

#include <cstdio>#include <cstring>#include <vector>#include <algorithm>#include <iostream>#include <map>#include <queue>#include <stack>#include <cmath>//#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define PF(x) cout << "debug: " << x << " ";#define EL cout << endl;#define PC(x) puts(x);typedef long long ll;#define CLR(x, v) sizeof (x, v, sizeof(x))using namespace std;const int INF = 0x5f5f5f5f;const int  N= 1000050;const int maxn=1e5+10;int n,k,top,root,q[maxn][30];char s[maxn];void insert(){    int len = strlen(s);    int now = root;    for(int i = 0;i < len;i++){        int tmp = s[i] - a + 0;        if(!q[now][tmp]) q[now][tmp] = ++top;        now = q[now][tmp];    }}int solve(int now){    int fg = 0,ans = 0;    for(int i = 0;i <26;i++){        if(q[now][i]){            fg = 1;            ans |= solve(q[now][i]) ^ 3;//可知子状态对父状态的贡献为^3再用|则得父状态        }    }    if(!fg)        ans = 1;//没有后续状态则此状态先手必败    return ans;}int main () {  //  freopen("in.txt","r",stdin);    cin>>n>>k;    while(n--){        scanf("%s",s);        insert();    }    int ans = solve(root);    if(ans == 3) cout<<"First"<<endl;    else if(k & 1 && ans == 2) cout<<"First"<<endl;    else cout<<"Second"<<endl;    return 0;}

 

codeforces 456d (字典树+DP)