博弈論 SG函數

(1) 玩家:2人;
(2) 道具:23張撲克牌;
(3) 規則:
遊戲雙方輪流取牌;
每人每次僅限於取1張、2張或3張牌;
撲克牌取光,則遊戲結束;
最後取牌的一方爲勝者。
想一下。。
首先申明一點,博弈的討論是在大家都玩的最好的情況下討論的。(如果2個玩家智商有差別,那就沒法討論了~~~~開個玩笑哈。)
介紹概念:P點 即必敗點,某玩家位於此點,只要對方無失誤,則必敗;
N點 即必勝點,某玩家位於此點,只要自己無失誤,則必勝。
定理:
一、 所有終結點都是必敗點P(上游戲中,輪到誰拿牌,還剩0張牌的時候,此人就輸了,因爲無牌可取);
二、所有一步能走到必敗點P的就是N點;
三、通過一步操作只能到N點的就是P點;
自己畫下圖看看。
x :0 1 2 3 4 5 6 7 8 9 10。。。
pos:P N N N P N N N P N N 。。。
所以若玩家甲位於N點。只要每次把P點讓給對方,則甲必勝;
反之,若玩家甲位於P點,他每次只能走到N點,而只要乙每次把P點讓給甲,甲必敗;
這裏好好理解下;
如果上面的理解的。請解決下面的題目:HDU 1846 2147(注意題目限制內存)(先2道練練手,做不出的話提示:找規律)
接下來介紹Nim遊戲(同樣引用杭電上的,懶的打字)
1.有兩個玩家;
2. 有三堆撲克牌(比如:可以分別是 5,7,9張);
3. 遊戲雙方輪流操作;
4. 玩家的每次操作是選擇其中某一堆牌,然後從中取走任意張;
5.最後一次取牌的一方爲獲勝方;
想一會:
還記得剛纔說的P點和N點嗎?P:必敗點,N:必勝點
先給出結論,這裏要用到位運算,異或:^
遊戲的某個位置(x1,x2,x3) x1,x2,x3表示3堆的個數。當且僅當 x1^x2^x3=0時,此點纔是必敗點P;
結論可以推廣到一般情況,即有n堆,(x1,x2,x3,…xn) 當且僅當x1^x2^x3…^xn=0時,此點纔是必敗點P;
如要看證明過程,鏈接在此 http://acm.hdu.edu.cn/forum/read.php?fid=9&tid=10617,看不懂的可以問 我(汗。。)
練習:HDU 2188 2149 (做不出的話先看下面的,然後多思考)
下面介紹sg函數(解決博弈問題的王道)
sg 即Graph Game,把博弈遊戲抽象成有向無環圖
(1) 有向無環圖
(2) 玩家1先移動,起點是x0
(3) 兩個玩家輪流移動
(4) 對於頂點x, 玩家能夠移動到的頂點集記爲F(x).
(5) 不能移動的玩家會輸掉遊戲
首先定義mex(minimal excludant)運算,這是施加於一個集合的運算,表示最小的不屬於這個集合的非負整數。例如mex{0,1,2,4}=3、 mex{2,3,5}=0、mex{}=0。
定義: 一個圖的Sprague-Grundy函數(X,F)是定義在X上的非負函數g(x),並且滿足:
g(x) = mex{g(y) : y∈F(x)}
看到這裏先好好理解一下sg值是怎麼求的;
如果在取子游戲中每次只能取{1,2,3},那麼各個數的SG值是多少?
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14…
g(x) 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2…
看看這個和上面那個圖的規律:
P-點: 即令 g(x) = 0 的 x 點!
N-點: 即令 g(x) > 0 的 x 點!
練習 HDU 1847 1849 1850 (做不出的話先看下面的,然後多思考)
最後看下組合博弈,就是把簡單的遊戲組合起來,比如3堆的可以看成3個一堆的遊戲。
定理:
假設遊戲 Gi的SG函數是gi, i=1,…,n, 則
G = G1 + … + Gn 的 SG函數是
g(x1,…,xn) = g1(x1)⊕…⊕gn(xn).
其中那個符合就是異或^。

SG函數模板

首先定義mex(minimal excludant)運算,這是施加於一個集合的運算,表示最小的不屬於這個集合的非負整數。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

對於一個給定的有向無環圖,定義關於圖的每個頂點的Sprague-Grundy函數g如下:g(x)=mex{ g(y) | y是x的後繼 },這裏的g(x)即sg[x]

例如:取石子問題,有1堆n個的石子,每次只能取{1,3,4}個石子,先取完石子者勝利,那麼各個數的SG值爲多少?

sg[0]=0,f[]={1,3,4},

x=1時,可以取走1-f{1}個石子,剩餘{0}個,mex{sg[0]}={0},故sg[1]=1;

x=2時,可以取走2-f{1}個石子,剩餘{1}個,mex{sg[1]}={1},故sg[2]=0;

x=3時,可以取走3-f{1,3}個石子,剩餘{2,0}個,mex{sg[2],sg[0]}={0,0},故sg[3]=1;

x=4時,可以取走4-f{1,3,4}個石子,剩餘{3,1,0}個,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;

x=5時,可以取走5-f{1,3,4}個石子,剩餘{4,2,1}個,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;

以此類推…..

x 0 1 2 3 4 5 6 7 8….

sg[x] 0 1 0 1 2 3 2 0 1….

計算從1-n範圍內的SG值。

f(存儲可以走的步數,f[0]表示可以有多少種走法)

f[]需要從小到大排序

1.可選步數爲1~m的連續整數,直接取模即可,SG(x) = x % (m+1);

2.可選步數爲任意步,SG(x) = x;

3.可選步數爲一系列不連續的數,用GetSG()計算

模板1如下(SG打表):

//f[]:可以取走的石子個數 
//sg[]:0~n的SG函數值 
//hash[]:mex{} 
 int f[N];//可以取走的石子個數 
int sg[N];//0~n的SG函數值 
int Hash[N];

void getSG(int n){ 
 memset(sg,0,sizeof(sg)); 
 for(int i = 1; i <= n; i++){ 
 memset(Hash,0,sizeof(Hash)); 
 for(int j = 1; f[j] <= i; j++) 
 Hash[sg[i-f[j]]] = 1; 
 for(int j = 0; j <= n; j++){ //求mes{}中未出現的最小的非負整數 
if(Hash[j] == 0){ 
 sg[i] = j; 
 break; 
 } 
發佈了68 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章