shell 【1】- 入門
1.概念
博弈論
概述:多個人在一定約束條件下,利用已掌握的資訊,使自身收益最大化的過程。全是抄的
公平
概述:每個人的操作是不是對等的。比如象棋就是不公平的,因為不能移動別人的棋子
資訊對等
概述:每個人所掌握的資訊是不是對等的。比如鬥地主就是資訊不對等的,因為你不知道別人手上的牌
2.經典模型(一)
巴什博弈
題目:有 \(n\) 個石子,兩個人輪流取,每次最多取 \(m\) 個,最少取 \(1\) 個,取完者獲勝,問先手有沒有必勝策略。
分析:作為大多數人都會的小奧題,它有一個很顯然的解法:每次對方取 \(k\) 個,就取 \(m+1-k\)
顯然:
\(\begin{cases}n\bmod(m+1)=0&\text{先手必敗}\\n\bmod(m+1)\ne0&\text{先手必勝}\end{cases}\)
程式碼:
#include<stdio.h>
int main(){
int n,m;
scanf("%d%d",&n,&m);
if(n % (m + 1)) printf("1");
else printf("0");
return 0;
}
威佐夫博弈
題目:有兩堆石子,兩個人輪流去,每次可以從一堆中取若干個或從兩堆中取相同的若干個,取完者獲勝,問先手有沒有必勝策略。
分析:
Step 1.列舉
由於先手有必勝策略的情況多於沒有的情況,於是我們來列舉少數的情況。(為了方便,預設第一堆數量小於等於第二堆)
先手沒有必勝策略的情況有:\((0,0),(1,2),(3,5),(4,7),(6,10),\cdots\)
規律:記第 \(i\) 項為 \((a_i,b_i)\),可得
\(a_0=b_0=0,a_i=\operatorname{mex}\{a_0,b_0,\dots,a_{i-1},b_{i-1}\},b_i=a_i+i,\operatorname{mex}\) 表示一個集合中最小沒有出現過的自然數
於是任何自然數都一定包含在先手沒有必勝策略的局面中(根據上文 \(\operatorname{mex}\)
通項公式下文再講
Step 2.轉換
Q. 記先手有必勝策略的對局 \(\alpha\),先手無必勝策略的對局 \(\beta\) ,那麼如何進行二者的轉換?
A. 兩點
- 對於一個 \(\beta\),任何一步都會將其變成一個 \(\alpha\)
- 對於一個 \(\alpha\),經過一步或多步總能將其變成一個 \(\beta\)
Q. 如果有一個 \(\alpha\,(a,b)\),如何轉換為 \(\beta\) 呢?
A. 顯然上文的回答是非常簡略的,那麼我們來詳細的考慮。
- \(a=b\),此時令 \(a-a,b-a\),即可變為 \((0,0)\)
- \(a=a_k,b=b_k\),此時 \((a,b)\ne\alpha\)
- \(a=a_k,b\gt b_k\),此時令 \(b\gets b_k\)
- \(a=a_k,b\lt b_k\),此時令 \(a-a_{b-a},b-b_{b-a}\gets\) 因為 \(b_{b-a}-a_{b-a}=b-a\)
- \(a\ne a_k\) 此時 \(a=b_i{}^*\),令 \(b\gets a_i\)
\(^{*}\tt{:}\) 因為所有自然數都在 \(a_0,a_1,\dots,b_0,b_1,\dots\) 中出現過(根據上文 \(\operatorname{mex}\) 定理),所以必然找到 \(b_i\) 使其等於 \(a\)
Step 3.解法
讀了這麼久的 Step 2,居然是沒有用的??
如果給定一個局勢 \((x,y)\),如何判斷是不是 \(\alpha\) 呢?
用上面的式子應算顯然不可能,我們要考慮通項公式
通項公式:記 \(\phi=\) 黃金比的倒數 \(=\dfrac{1+\sqrt5}{2}\),則 \(a_i=\left\lfloor i\phi\right\rfloor,b_i=\left\lfloor i\phi^2\right\rfloor\)
於是程式碼如下:(威佐夫博弈模板)
#include<stdio.h>
#include<math.h>
int main(){
int n,m,t;
scanf("%d%d",&n,&m);
if(n > m) t = n,n = m,m = t; // 保證n<m
double phi = (1.000 + sqrt(5.000)) / 2.000; // 計算phi
if(florr(phi * (m - n)) == n) printf("0"); // 如果是beta,則,n=a[m-n]=floor(phi*(m-n))
else printf("1");
return 0;
}
3.博弈點搜尋
對於前兩個經典博弈例子,都有神奇的 \(\mathit{O}(1)\) 公式,但有沒有涵蓋大部分博弈的解法呢,答案是:有!!
這裡的內容與威佐夫博弈 Step2 銜接
而且,還是每天都給我們幫助,讓我們受益匪淺的——DFS!!
驚不驚喜意不意外 不過標題似乎就說明了
DFS 遞迴形成的一棵樹,我們將其稱之為\(\,\)博弈樹。
DFS 過程:把狀態放到 DFS 函式的引數裡,並且為每一種狀態打上標記,還可以用記憶化搜尋優化已經搜尋過的節點
那我們怎麼標記呢?\(\tt3\) 條規則 \(\downarrow\)
- 終止狀態標記為 必敗點
- 一步可以到達 必敗點 的都是 必勝點
- 一步只能到達 必勝點 的都是 必敗點
有點難以理解?不妨轉化一下規則 \(\tt{2,3}\)
- 一步只能到達 必勝點 的都是 必敗點
- 一步只能到達 必敗點 的都是 必勝點
- 一步可以到達 必勝點 和 必敗點 的也是 必勝點
4.Nim遊戲
\(\tt{Nim}\) 遊戲規則如下:
有 \(n\) 堆石子 \(a_1,a_2,\dots a_n\),兩人輪流從任意一組取若干個石子,誰取完誰贏,問先手有沒有必勝策略。
答案:\(\begin{cases}a_1\operatorname{xor}a_2\cdots\operatorname{xor}a_n=0&\text{先手必敗}\\a_1\operatorname{xor}a_2\cdots\operatorname{xor}a_n\ne0&\text{先手必勝}\end{cases}\)
其中 \(\operatorname{xor}\) 表示異或運算 \(\oplus\)
證明:
這個演算法成立需要滿足三個條件:
- 終止狀態是必敗節點
- 由一個必敗節點,無論怎麼走都是必勝節點
- 由一個必勝節點,存在一種走法到必敗節點
條件 \(\tt{1:}\) 因為 \(0\operatorname{xor}\cdots0=0\),所以成立
條件 \(\tt{2:}\) 記我們要取的是第 \(i\) 堆,根據 異或 的性質
\(a_1\operatorname{xor}a_2\cdots\operatorname{xor}a_{i-1}\operatorname{xor}a_{i+1}\cdots\operatorname{xor}a_n=a_i\)
而只有 \(a_i\operatorname{xor}a_i=0\) ,所以無論把 \(a_i\) 改成什麼,都得不到必敗狀態
條件 \(\tt{3:}\) 如果 \(a_1\operatorname{xor}a_2\cdots\operatorname{xor}a_n=x\),此時可以找到一個 \(a_i\),\(a_i\) 在 \(x\) 的最高二進位制位上是 \(1\),那麼 \(a_i\operatorname{xor}x\ge0\),於是令 \(a_i\gets a_i\operatorname{xor}x\) 即可
證畢。
程式碼:
#include<stdio.h>
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,res = 0;
scanf("%d",&n);
for(int i = 1;i <= n;++i){
int ai;
scanf("%d",&ai);
res ^= ai;
}
if(res) puts("Yes");
else puts("No");
}
return 0;
}
5.組合博弈
考慮一枚(或多枚)棋子,在一個 \(\rm{DAG}\)(有向無環圖)中,兩個人輪流將其進行移動 \(1\) 步,無法移動者輸。
棋子可以理解為狀態,有向無環圖就是由不同的狀態構成的有向無環圖,移動就代表進入後繼狀態。
這裡的博弈遊戲中,定義 \(\operatorname{SG}\) 函式 \(\operatorname{SG}(x)=\operatorname{mex}\{\operatorname{SG}(y)\mid y\) 是 \(x\) 的後繼狀態集 \(\}\) (它的作用後面再說)
\(\operatorname{mex}\) 還是一個集合中最小沒出現過的自然數
\(\operatorname{SG}\) 函式性質如下
- \(\operatorname{SG}(\)終止節點\()=0\)(因為它的後繼狀態集是空集)
- \(\operatorname{SG}(\)非終止節點\()\) 分兩種情況來考慮
- \(\operatorname{SG}(x)=0\),則 \(\operatorname{SG}(y)\ne0,y\) 是 \(x\) 的後繼狀態集
- \(\operatorname{SG}(x)\ne0\),則存在 \(\operatorname{SG}(y)=0,y\) 是 \(x\) 的後繼狀態集
是不是和之前的必勝點和必敗點有點像?其實對於一枚棋子移動的問題, \(\operatorname{SG}=0\) 就可以直接判斷是必敗點,反之為必勝點。
那如果是多枚棋子的移動呢?如果有 \(n\) 枚棋子,此時就會有 \(n\) 個局面 \(G_1,G_2,\dots,G_n\),那麼它們的和 \(S\) 滿足 \(\operatorname{SG}(S)=\operatorname{SG}(G_1)\operatorname{xor}\operatorname{SG}(G_2)\cdots\operatorname{xor}\operatorname{SG}(G_n)\)
和 \(\tt Nim\) 如出一轍!!!
5.總結
博弈論題往往是程式碼短小精悍,思維難度很高,總而言之,重要的是必勝必敗點的性質、作用以及毒瘤的 \(\operatorname{SG}\) 函式。
qwq