CodeForces - 456D A Lot of Games(字典树+博弈)
生活随笔
收集整理的這篇文章主要介紹了
CodeForces - 456D A Lot of Games(字典树+博弈)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出n個字符串,現在有兩個人玩一個游戲,游戲規則是兩人輪流構造同一個字符串,每次可以向末尾添加一個字母,必須保證添加字母后的字符串是n個字符串其中之一的前綴,不能操作者算輸,兩個人需要進行k次游戲,第一次游戲由先手開始,之后輸掉本局游戲的人為下一局游戲的先手,現在問誰能贏得最后一局的游戲
題目分析:考慮到需要對數量較大的前綴進行操作,我們可以使用字典樹來維護,這樣整個題目就變成了字典樹上的博弈,我們可以從葉子結點的狀態不斷向上轉移,最后轉移到字典樹的根節點,又因為字典樹的根節點是一個不存在的結點,所以我們對每個節點定義為:接下來一步的狀態,因為最后無法操作的人會輸掉比賽,所以葉子結點就是必敗態,要分清楚我們現在有四個狀態:
顯然狀態一二互斥,狀態三四互斥,這樣一來將狀態轉移到根節點然后分類討論就是答案了:
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<set> #include<cmath> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;char s[N];int trie[N][26],cnt,val[N];void insert() {int pos=0;for(int i=0;s[i];i++){int to=s[i]-'a';if(!trie[pos][to])trie[pos][to]=++cnt;pos=trie[pos][to];} }void dfs(int pos)//val 1:必敗 2:必勝 3:可勝可敗 4:不能確定 {bool win=false;//必勝bool lose=false;//必敗 bool flag=true;//是否為子節點 for(int i=0;i<26;i++)if(trie[pos][i]){dfs(trie[pos][i]);if(val[trie[pos][i]]==1||val[trie[pos][i]]==4)win=true;if(val[trie[pos][i]]==2||val[trie[pos][i]]==4)lose=true; flag=false;}if(flag)val[pos]=1;else{if(win&&lose)val[pos]=3;else if(win)val[pos]=2;else if(lose)val[pos]=1;elseval[pos]=4;} }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);while(n--){scanf("%s",s);insert();}dfs(0);if(val[0]==1){puts("Second");}else if(val[0]==2){if(m&1)puts("First");elseputs("Second");}else if(val[0]==3){puts("First");}else{puts("Second");}return 0; }?
總結
以上是生活随笔為你收集整理的CodeForces - 456D A Lot of Games(字典树+博弈)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 456C Bo
- 下一篇: 牛客 - 阔力梯的树(树上启发式合并)