題目連接c++
題意:數組
A和B輪流在建造一個字,每次添加一個字符,要求是給定的n個串的某一個的前綴,不能添加字符的人輸掉遊戲,輸掉的人先手下一輪的遊戲。問A先手,通過k輪遊戲,最後勝利的人是誰。code
思路:blog
很顯然先將n個字符串插入到字典樹上,由於字典樹上有分叉,不能僅僅判斷字符串長度奇偶性來判斷。字典樹當作無環的狀態圖,若是按照拓撲排序逆序進行排序,在判斷每一個節點的時候,它的後繼都已經判斷過了。定義兩個數組can_win[u], can_lose[u],表示u節點走下去「可能贏嗎?」以及u節點走下去」可能輸嗎?「,那麼取反就是必勝和必敗態了,「可能贏」<-對手下一步不可能贏,」可能輸「<-對手下一步不可能輸。排序
代碼:遊戲
#include <bits/stdc++.h> const int N = 1e5 + 5; char str[N]; int ch[N][26]; int sz; bool can_win[N], can_lose[N]; void init() { memset (ch[0], 0, sizeof (ch[0])); sz = 1; } void insert(char *s) { int u = 0, c; for (int i=0; s[i]; ++i) { c = s[i] - 'a'; if (!ch[u][c]) { memset (ch[sz], 0, sizeof (ch[sz])); ch[u][c] = sz++; } u = ch[u][c]; } } void DFS(int u) { can_win[u] = can_lose[u] = false; bool is_leaf = true; for (int c=0; c<26; ++c) { int v = ch[u][c]; if (v) { is_leaf = false; DFS (v); can_win[u] |= !can_win[v]; can_lose[u] |= !can_lose[v]; } } if (is_leaf) { can_lose[u] = true; } } int main() { int n, k; scanf ("%d%d", &n, &k); init (); for (int i=0; i<n; ++i) { scanf ("%s", str); insert (str); } DFS (0); if (!can_win[0]) { puts ("Second"); //of course! } else if (can_lose[0]) { puts ("First"); //can lose && can win, control! } else { //can win && !can lose, change A and B every turn! printf ("%s\n", (k & 1) ? "First" : "Second"); } return 0; }