(組合遊戲)SG函式與SG定理詳解
有一段時間沒記錄知識類的部落格了,這篇部落格就說一下SG函式和SG定理吧
什麼是組合遊戲
在競賽中,組合遊戲的題目一般有以下特點
- 題目描述一般為Alice、Bob 2人做遊戲
- Alice、Bob交替進行某種遊戲規定的操作,每操作一次,選手可以在有限的操作(操作必須合法)集合中任選一種。
- 對於遊戲的任何一種可能的局面,合法的操作集合只取決於這個局面本身,不取決於其它因素(跟選手,以前的所有操作無關)
- 如果當前選手無法進行合法的操作,則為負
舉個例子現在有一個數0,小明小紅2人每次可以輪流在當前數加 1~3,誰先湊到21誰就贏
這個描述就符合上面的條件:
- 小明小紅(滿足1)
- 每次輪流在當前數上加1~3(滿足2)
- 當前能進行的操作只取決於這個數本身(也就是這個局面),如果這個數為20,可操作的集合為+{1},如果為12,可操作的集合為+{1,2,3}(滿足3)
- 如果數字已經為21了,則不可能往上在加數字,可操作集合為\(Φ\),當前選手為負(滿足4)
必勝點和必敗點的概念
- 必敗點(P點) 前一個(previous player)選手將取勝的點稱為必敗點
- 必勝點(N點) 下一個(next player)選手將取勝的點稱為必勝點
比如現在數字已經為18了,那麼當前操作人只要給數字+3則必勝,我們就把在此位置稱為必勝點(正常操作情況下,別槓說都18偏要+2。。。。)
必勝點和必敗點的性質:
- 所有的終結點都是必敗點
- 從任何必勝點操作,至少有一種方式進入必敗點
- 無論如何操作, 從必敗點都只能進入必勝點.
Sprague-Grundy(SG)定理
遊戲和的SG函式
等於各個遊戲SG函式的Nim和
。這樣就可以將每一個子遊戲分而治之,從而簡化了問題。而Bouton
定理就是Sprague-Grundy
定理在Nim遊戲中的直接應用,因為單堆的Nim遊戲 SG函式滿足 SG(x) = x。
Nim和 : 各個數相異或的結果
SG函式
先定義mex(minimal excludant)
運算,這是施加於一個集合的運算,表最小的不屬於這個集合的非負整數。例如\(mex\{0,1,2,4\}=3、mex\{2,3,5\}=0、mex\{\}=0\)。
對於任意狀態 x , 定義 SG(x) = mex(S),其中 \(S\)
的終態必然是空集,所以\(SG\) 函式的終態為 \(SG(x) = 0\) ,當且僅當x 為必敗點P時
取石子問題
有1堆n個的石子,每次只能取{ 1, 3, 4 }個石子,先取完石子者勝利,那麼各個數的SG值為多少?
SG[0]=0,f[]={1,3,4},
x=1 時,可以取走1 - f{1}個石子,剩餘{0}個,所以 SG[1] = mex{ SG[0] }= mex{0} = 1;
x=2 時,可以取走2 - f{1}個石子,剩餘{1}個,所以 SG[2] = mex{ SG[1] }= mex{1} = 0;
x=3 時,可以取走3 - f{1,3}個石子,剩餘{2,0}個,所以 SG[3] = mex{SG[2],SG[0]} = mex{0,0} =1;
x=4 時,可以取走4- f{1,3,4}個石子,剩餘{3,1,0}個,所以 SG[4] = mex{SG[3],SG[1],SG[0]} = mex{1,1,0} = 2;
x=5 時,可以取走5 - f{1,3,4}個石子,剩餘{4,2,1}個,所以SG[5] = mex{SG[4],SG[2],SG[1]} =mex{2,0,1} = 3;
以此類推…
x 0 1 2 3 4 5 6 7 8…
SG[x] 0 1 0 1 2 3 2 0 1…
由上述例項我們就可以得到SG函式值求解步驟,那麼計算1~n的SG函式值步驟如下:
1、使用 陣列f 將 可改變當前狀態 的方式記錄下來。
2、然後我們使用 另一個數組 將當前狀態x 的後繼狀態標記。
3、最後模擬mex運算,也就是我們在標記值中 搜尋 未被標記值 的最小值,將其賦值給SG(x)。
4、我們不斷的重複 2 - 3 的步驟,就完成了 計算1~n 的函式值。
模板如下:
//f[N]:可改變當前狀態的方式,N為方式的種類,f[N]要在getSG之前先預處理
//SG[]:0~n的SG函式值
//S[]:為x後繼狀態的集合
int f[N],SG[MAXN],S[MAXN];
void getSG(int n){
int i,j;
memset(SG,0,sizeof(SG));
//因為SG[0]始終等於0,所以i從1開始
for(i = 1; i <= n; i++){
//每一次都要將上一狀態 的 後繼集合 重置
memset(S,0,sizeof(S));
for(j = 0; f[j] <= i && j <= N; j++)
S[SG[i-f[j]]] = 1; //將後繼狀態的SG函式值進行標記
for(j = 0;; j++) if(!S[j]){ //查詢當前後繼狀態SG值中最小的非零值
SG[i] = j;
break;
}
}
}
其實不難發現,Nim遊戲就是一個很典型的用SG定理解決的問題,因為Nim遊戲在一堆n個石子中可以取1-n個石子,所以單獨這一堆石子的SG值為\(mex(n−1,n−2,n−3,...,n−n)=n\),根據SG定理,每一堆石子總數相互異或即為答案
本文是參考其他博文+自己理解,整理而來,現附上參考博文連結:
https://blog.csdn.net/luomingjun12315/article/details/45555495
https://blog.csdn.net/SM_545/article/details/77340690