首先存這些字符,用trie來存,通過trie就很容易聯(lián)想到樹型DP,這里的DP就不是取最優(yōu)值之類的了,而是用來弄到達(dá)某個(gè)節(jié)點(diǎn)的勝負(fù)情況。
我們首先設(shè)節(jié)點(diǎn)v,win[v]代表已經(jīng)組裝好的字符剛好匹配到v了,然后需要進(jìn)行下一步匹配時(shí),先手是否可以贏,lose[v]則代表先手是否會(huì)輸。
葉節(jié)點(diǎn),win[v] = false, lose[v] = true.
其他節(jié)點(diǎn) win[v] = win[v] | !win[child], lose[v] = lose[v] | !lose[child]. (因?yàn)槊看乌A的人,下一個(gè)就不是先手,所以結(jié)果肯定是跟下一個(gè)節(jié)點(diǎn)的贏成對(duì)立關(guān)系)。
如若win[0] = true , lose[0] = true則意味著第一局的人可以操控結(jié)果,否則按照k的次數(shù)來判斷是否可以贏。
#include#include #define N_max 123456 #define sigma_size 26 using namespace std; bool win[N_max], lose[N_max]; int n, k; char st1[N_max]; class Trie{ public: int ch[N_max][sigma_size]; int sz; Trie() { sz=0; memset(ch[0], 0, sizeof(ch[0])); } int idx(char c) { return c-'a'; } void insert(char *s) { int l = strlen(s), u = 0; for (int i = 0; i < l; i++) { int c = idx(s[i]); if (!ch[u][c]) { ch[u][c] = ++sz; memset(ch[sz], 0, sizeof(ch[sz])); } u = ch[u][c]; } } }; Trie T; void init() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%s", st1); T.insert(st1); } } void dfs(int v) { bool is_leaf = true; win[v] = false; lose[v] = false; for (int i = 0; i < sigma_size; i++) { int tmp = T.ch[v][i]; if (tmp) { is_leaf = false; dfs(T.ch[v][i]); win[v] |= !win[T.ch[v][i]]; lose[v] |= !lose[T.ch[v][i]]; } } if (is_leaf) { win[v] = false; lose[v] = true; } } void ans(bool res) { puts(res? "First":"Second"); } void solve() { dfs(0); if (win[0] && lose[0]) ans(true); else if (win[0]) ans(k&1); else ans(0); } int main() { init(); solve(); }
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com