【學習】博弈遊戲

博弈問題

所討論的博弈問題滿足以下條件:

  1. 玩家只有兩個人,輪流做出決策,且操作公平。
  2. 遊戲的狀態集有限,保證遊戲在有限步後結束.
  3. 博弈雙方都使用最優決策。

一個遊戲有兩個狀態,我們稱爲必勝態和必敗態,他們的關係:

  • 必勝態表示,從當前狀態可以轉移到一個必敗態。
  • 必敗態表示,從當前狀態無法轉移到一個必敗態。

也就是說,一個狀態不是必勝態,就是必敗態。

知識點

SG函數

SG[x]=mex{SG[y]}

其中yx 所有的後繼狀態(通過操作改變當前狀態爲後繼狀態),mex 是最小的沒有出現的連續自然數。

遊戲的和

遊戲x1,x2,...,xn 的和爲x ,且x={x1,x2,...,xn}
理解爲x 是由x1,x2,...,xn 構成的新遊戲。

SG定理

如果一個遊戲的所有子游戲相互獨立(即一個子遊戲的操作不會影響其他的子游戲),那麼

SG[x]=SG[x1] xor SG[x2] xor ... xor SG[xn]

文字表述爲,一些遊戲的和的SG 函數等於各個遊戲SG 函數的亦或和。

題目

BZOJ 2463 [中山市選2009]誰能贏呢?

思路:

可以證明,偶數的棋盤一定會被1×2 的牌覆蓋,奇數的棋盤一定可以被1×2 的牌覆蓋多出一個,所以說偶數的棋盤先手必勝,因爲它只要走牌的後一個點一定可以贏,反之,奇數的棋盤先手必敗。

代碼:2463.cpp

BZOJ 1115 [POI2009]石子游戲

思路:

差分以後,就是經典的階梯Nim 取石子的模型,後面的端點。

代碼:1115.cpp

BZOJ 4202 石子游戲

思路:

類似於階梯Nim 遊戲,對於一個點爲根來說,所有深度與其的差是偶數的點是無效的,因爲當A 做了這個操作以後,另一方B 可以馬上把A 移動的石子再向上移動,奇數深度的點保持原來的狀態。
動態加點需要link cut tree 的支持,所以我們建立兩顆lct 把深度的奇偶分開維護,修改操作相當於給一個點到根的路徑上的亦或和再抑或一個數,加點相當於在兩顆lct 中都新link 一個點。附:LCT學習筆記
現在還有最多取m 個的限制,可以從SG 值的角度來考慮,前m+1 個的SG 值,是從0m 的,但是第m+2SG 就無法選擇第1SG 了,取mex 後他的SG 值就是0 ,所以不難發現,SG 值表示的數量,是關於模m+1 同餘的。
換種角度看,m+1 是一個特殊的取值,這個值一次一定去不到,兩次一定可以取完,所以說大於m+1 的點,先手進行一次取值,後手可以緊跟着再%m+1 的地方移動一次,便到前面模m+1 同餘的一樣的地方去,這樣的操作是沒有意義的,所以說可以把權值%(m+1) ,直接按上面的步驟做完即可。

代碼:4202.cpp

BZOJ 4347 [POI2016]Nim z utrudnieniem

思路:

如果再取走之後,剩餘的石子堆的疑異或和爲0 ,那麼當前的選擇就是一種合法的方案。
所以問題轉換爲求異或和爲K 的取值的方案數,其中K 是所有權值的異或和。
狀態:f[i][j][k] 表示前i 堆石頭,現在取得堆數modd=j ,異或和是k 的方案數。
轉移:f[i][j][k]=f[i1][j][k]+f[i1][(j1)mod d][k xor a[i]]
如果我們對a 數組進行排序,那麼每次異或和的最大值是2×a[i]
這樣算下來,總的時間複雜度是O(md) 的。
但是這個題的空間限制是64MB ,只滾動第一維還是不夠的,所以可以直接像揹包那樣,倒着轉移,直接省去第一維,但是0 需要從d1 轉移,d1 的狀態改變後,就無法轉移了,所以用一個輔助數組,先把0 轉移完,然後就可以了去掉第一維了。

代碼:4347.cpp

BZOJ 4600 [Sdoi2016]硬幣遊戲

思路:

代碼:4600.cpp

BZOJ 4134 ljw和lzr的hack比賽

思路:

首先划子遊戲,拔一顆子樹看成一個子遊戲,顯然,子游戲之間是互相獨立的。
一個決策的狀態值是以這個點到跟的路徑上的所有點的非本鏈上的孩子爲根的子游戲的異或和。
子樹的SG 值是子樹內所有決策狀態值的mex
所以我們用二進制Trie 來維護異或和與mex 操作,Trie 的節點記錄當前的子樹內已有的點的個數。每一棵樹記錄一個永久化的標記,標記代表對整棵樹的異或。
對原樹進行dfs ,所有的Trie 進行啓發式合併,對於最大樹的修改,直接打標記,其他樹的元素直接全部插入到大樹當中。
統計答案時,記錄當前點的所有子樹的異或和,向下dfs 的子樹,把子樹對應的異或消掉,繼續向下搜。

代碼:4134.cpp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章