主頁 >  其他 > 《博弈論全家桶》(ACM / OI)(超全的博弈論 / 組合游戲大合集)

《博弈論全家桶》(ACM / OI)(超全的博弈論 / 組合游戲大合集)

2021-02-21 11:29:46 其他

整理的演算法模板合集: ACM模板

點我看演算法全家桶系列!!!

實際上是一個全新的精煉模板整合計劃


我更愿稱之為組合游戲hhh

0x00 公平組合游戲ICG

若一個游戲滿足:

  • 由兩名玩家交替行動

  • 在游戲行程的任意時刻,可以執行的合法行動與輪到哪名玩家無關

  • 游戲中的同一個狀態不可能多次抵達,游戲以玩家無法行動為結束,且游戲一定會在有限步后以非平局結束

則稱該游戲為一個公平組合游戲

例如 Nim 博弈屬于公平組合游戲,而普通的棋類游戲,比如圍棋,就不是公平組合游戲,因為圍棋交戰雙方分別只能落黑子和白子,勝負判定也比較復雜,不滿足條件2和條件3,

0x01 有向圖游戲(博弈圖)

給定一個有向無環圖,圖中有一個唯一的起點,在起點上放有一枚棋子,兩名玩家交替地把這枚棋子沿有向邊進行移動,每次可以移動一步,無法移動者判負,該游戲被稱為有向圖游戲,

任何一個公平組合游戲都可以轉化為有向圖游戲,具體方法是,把每個局面看成圖中的一個節點,并且從每個局面向沿著合法行動能夠到達的下一個局面連有向邊, 轉化為有向圖游戲,也稱繪制了它的博弈狀態圖(簡稱博弈圖或游戲圖),

這樣,對于組合游戲中的每一次對弈(每一局游戲),我們都可以將其抽象成游戲圖中的一條從某一頂點到出度為 0 0 0 的點的路徑,

組合游戲向圖的轉化,并不單單只是為了尋找一種對應關系,它可以幫助我們淡化游戲的實際背景,強化游戲的數學模型,更加突出游戲 的數學本質,

0x02 先手必勝和先手必敗

  • 先手必勝狀態 : 先手行動以后,可以讓剩余的狀態變成必敗狀態 留給對手(下一步是對手(后手)的局面),

  • 先手必敗狀態 : 不管怎么操作,都達不到必敗狀態,換句話說,如果無論怎么行動都只能達到一個先手必勝狀態留給對手,那么對手(后手)必勝,先手必敗,

簡化一下就是:

  • 先手必勝狀態:可以走到某一個必敗狀態

  • 先手必敗狀態:走不到任何一個必敗狀態

因為我們當前走到的狀態是送給對手的狀態hhh

通常先手是 A l i c e \tt Alice Alice ,后手是 B o b \tt Bob Bob

定理:

定理 2.1: 沒有后繼狀態的狀態是必敗狀態,

定理 2.2: 一個狀態是必勝狀態當且僅當存在至少一個必敗狀態為它的后繼狀態,

定理 2.3: 一個狀態是必敗狀態當且僅當它的所有后繼狀態均為必勝狀態,

如果博弈圖是一個有向無環圖,則通過這三個定理,我們可以在繪出博弈圖的情況下用 O ( N + M ) O(N+M) O(N+M) 的時間(其中 N N N 為狀態種數, M M M 為邊數)得出每個狀態是必勝狀態還是必敗狀態,

0x03 必勝點和必敗點

必敗點(P點) 前一個(previous player)選手將取勝的點稱為必敗點

必勝點(N點) 下一個(next player)選手將取勝的點稱為必勝點

(1) 所有終結點是必敗點(P點)

(2) 從任何必勝點(N點)操作,至少有一種方法可以進入必敗點(P點)

(3)無論如何操作, 從必敗點(P點)都只能進入必勝點(N點)

0x04 有向圖的核

給定一張DAG圖 < V , E > <V,E> <V,E>,如果 V V V 的一個點集 S S S 滿足:

  • S S S 是獨立集(集合內的點互不相通)

  • 集合 V ? S V-S V?S 中的點都可以通過一步到達集合 S S S 中的點( V ? S V-S V?S S S S V V V 中的補集)

則稱 S S S 是圖 V V V 的一個

結論: 核內節點對應 SG 組合游戲的必敗態

因為 Alice 當前的棋子在 S S S 中,由于 S S S 是獨立集,也就意味著 Alice 只能將棋子從 S S S 移動到 V ? S V-S V?S

而 Bob又可以通過一步移動將棋子從 V ? S V-S V?S 移動到了 S S S,這樣 Alice 就好像是被支配了一樣,被迫把棋子移動到了沒有出度的必敗節點,Alice 必敗,Bob必勝!


0x10 幾個經典組合游戲

0x11 尼姆游戲 N i m G a m e \tt Nim\ Game Nim Game

題目大意

給定 N N N 堆物品,第i堆物品有Ai個,兩名玩家輪流行動,每次可以任選一堆,取走任意多個物品,可把一堆取光,但不能不取,取走最后一件物品者獲勝,兩人都采取最優策略,問先手是否必勝,


我們把這種游戲稱為 Nim 博弈,把游戲程序中面臨的狀態稱為局面,整局游戲第一個行動的稱為先手,第二個行動的稱為后手,若在某一局面下無論采取何種行動,都會輸掉游戲,則稱該局面必敗

所謂采取最優策略是指,若在某一局面下存在某種行動,使得行動后對手面臨必敗局面,則優先采取該行動,同時,這樣的局面被稱為必勝,我們討論的博弈問題一般都只考慮理想情況,即兩人均無失誤,都采取最優策略行動時游戲的結果,

Nim 博弈不存在平局,只有先手必勝和先手必敗兩種情況,

Solution

通過繪制博弈圖,可以在 O ( Π i = 1 n a i ) \mathcal O(\Pi _{i=1}^n\ a_i) O(Πi=1n? ai?) 的時間內求出該局是否先手必贏 but,這個時間復雜度太高了

結論:定義 Nim 和為 a 1 ⊕ a 2 ⊕ . . . ⊕ a n a_1\oplus a_2\oplus...\oplus a_n a1?a2?...an?

當且僅當 N i m Nim Nim 和為 0 0 0 時,該狀態為先手必敗狀態 否則該狀態為先手必勝狀態

考慮證明:


我們只需要證明 a 1 ⊕ a 2 ⊕ . . . ⊕ a n =? 0 a_1\oplus a_2\oplus...\oplus a_n\not=0 a1?a2?...an??=0 是先手必勝狀態, a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0 是先手必敗狀態即可,

我們可以從先手必敗和先手必勝狀態的定義出發,也就是說我們只需要證明下面的三個定理即可(博弈論結論證明都是朝著這個方向證明的):


定理1: 沒有后繼狀態的狀態為必敗狀態

定理2: 對于 a 1 ⊕ a 2 ⊕ . . . ⊕ a n =? 0 a_1\oplus a_2\oplus...\oplus a_n\not=0 a1?a2?...an??=0 的局面,一定存在某種移動使得 a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0 (必勝狀態一定能到達一個必敗狀態)

定理3: 對于 a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0 的局面,一定不存在某種移動使得 a 1 ⊕ a 2 ⊕ . . . ⊕ a n ≠ 0 a_1\oplus a_2\oplus...\oplus a_n \neq0 a1?a2?...an??=0 (必敗狀態一定不能到達任何必敗狀態)


定理1證明: 沒有后繼狀態的狀態(必敗點)只有一個,即全 0 0 0 局面 此時 a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0,定理1得證 □


定理2證明: 我們不妨假設 a 1 ⊕ a 2 ⊕ . . . ⊕ a n = k =? 0 a_1\oplus a_2\oplus...\oplus a_n=k\not=0 a1?a2?...an?=k?=0,如果我們將 a i a_i ai? 改為 a i ′ a_i' ai? ,則 a i ′ = a i ⊕ k a_i'=a_i\oplus k ai?=ai?k

k k k 在二進制下最高位的 1 1 1 在第 x x x 位,則一定有奇數個 a i a_i ai? 的二進制下在 x x x 位為 1 1 1(異或運算,相同為 1 1 1 ),

因為 a i ⊕ k = a i ′ < a i a_i\oplus k=a_i'<a_i ai?k=ai?<ai? ,所以我們就可以從 a i a_i ai? 這堆中拿走 a i ⊕ k = a i ′ a_i\oplus k=a_i' ai?k=ai? 個石子( a i > a i ′ a_i>a_i' ai?>ai?,所以有足夠的石子去拿),則 a i a_i ai? 就變成了 a i ? ( a i ? a i ⊕ k ) = a i ⊕ k = a i ′ a_i-(a_i-a_i\oplus k)=a_i\oplus k=a_i' ai??(ai??ai?k)=ai?k=ai?

則剩下的 Nim 和為 a 1 ⊕ a 2 ⊕ ? ⊕ a i ⊕ k ⊕ a i + 1 ⊕ ? ⊕ a n = k ⊕ k = 0 a_1\oplus a_2\oplus \cdots \oplus a_i\oplus k\oplus a_{i+1}\oplus\cdots \oplus a_n=k\oplus k=0 a1?a2??ai?kai+1??an?=kk=0,定理2得證 □


定理3證明: 當前狀態為 a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0 ,我們僅需證明不管怎么拿,Nim 和都不會為 0 0 0

我們使用反證法:

假設我們從 a i a_i ai? 拿走若干石子變為 a i ′ a_i' ai? ,使得Nim和變為 0 0 0

則說明存在:

a 1 ⊕ a 2 ⊕ ? ⊕ a i ′ ⊕ a i + 1 ⊕ ? ⊕ a n = 0 a_1\oplus a_2\oplus \cdots \oplus a_i' \oplus a_{i+1}\oplus\cdots \oplus a_n =0 a1?a2??ai?ai+1??an?=0

但我們知道當前狀態 Nim和為 0 0 0,即:

a 1 ⊕ a 2 ⊕ ? ⊕ a i ⊕ a i + 1 ⊕ ? ⊕ a n = 0 a_1\oplus a_2\oplus \cdots \oplus a_i \oplus a_{i+1}\oplus\cdots \oplus a_n =0 a1?a2??ai?ai+1??an?=0

兩式異或起來得出 a i = a i ′ a_i=a_i' ai?=ai? ,很明顯這是在原地轉圈,不是合法的移動,不存在這種走法,定理3得證 □

定理 1 ~ 3 得證,故 a 1 ⊕ a 2 ⊕ . . . ⊕ a n =? 0 a_1\oplus a_2\oplus...\oplus a_n\not=0 a1?a2?...an??=0 是先手必勝狀態, a 1 ⊕ a 2 ⊕ . . . ⊕ a n = 0 a_1\oplus a_2\oplus...\oplus a_n=0 a1?a2?...an?=0 是先手必敗狀態, Nim 游戲解題結論得證,

Code

#include <cstdio>
using namespace std;
int n, x, ans;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) {
        scanf("%d", &x);
        ans ^= x;
    }
    if(ans == 0) puts("No");
    else puts("Yes");
    return 0;
}

0x12 巴什博弈 B a s h G a m e \tt Bash \ Game Bash Game

有 1 堆石子,總個數是 n ,兩名玩家輪流在石子堆中拿石子,每次至少取 1 個,至多取 m 個,取走最后一個石子的玩家為勝者,判定先手和后手誰勝,

結論

( m + 1 ) ∣ n (m+1)\ |\ n (m+1) n (整除)則先手必敗 否則先手必勝

考慮證明:

情況一: n ≤ m n\le m nm 時,顯然先手獲勝

情況二: n = m + 1 n=m+1 n=m+1 時,先手最多可取走 m m m 個,無論其取走多少個,剩下的后手總能一次取完,

情況三: ( m + 1 ) ∣ n (m+1)|n (m+1)n ,假設先手拿走了 x x x 個,那么后手一定可以拿走 ( m + 1 ) ? x (m+1)-x (m+1)?x 個,這樣無論怎么拿剩下的石頭個數都將是 m + 1 m+1 m+1 的倍數,那么最后一次取的時候石頭個數必定還剩下 m + 1 m+1 m+1 個,即情況二,

否則的話,先手可以取走模 m + 1 m+1 m+1 余數個數的石頭 此時轉換為 ( m + 1 ) ∣ n (m+1)|n (m+1)n 的局面 送給后手,這樣后手變成了先手,也就就是后手必敗,

Code

可以直接模擬

int main() {
	scanf("%d%d", &n, &m);
    if (n % (m + 1))
        puts("first win");
    else
        puts("second win");

    return 0;
}

也可以轉換成SG 游戲使用 SG 函式 (SG函式見下節)

bool vis[N];
int sg[N];
void SG(int n, int m) {
    for (int i = 0; i <= n; ++i) {
        memset(vis, 0, sizeof(vis));
        for (int j = max(i - m, 0), j < i; ++j)
            vis[sg[j]] = 1;
        for (int j = 0; j <= n; ++j)
            if (!vis[j]) {
                sg[i] = j;
                break;
            }
    }
}
int main() {
	scanf("%d%d", &n, &m);
    SG(n, m);
    puts(sg[n] ? "first win" : "second win");
    return 0;
}

0x13 威佐夫博弈 W y t h o f f G a m e \tt Wythoff\ Game Wythoff Game

Problem A 取石子游戲(POJ 1063)

有兩堆石子,石子數可以不同,兩人輪流取石子,每次可以在一堆中取,或者從兩堆中取走相同個數的石子,數量不限,取走最后一個石頭的人獲勝,判定先手是否必勝,

Solution

一共只有兩堆石子,我們可以把問題放到到二維坐標系上,設 x , y x,y x,y 分別對應兩堆的石子的數量,

模擬發現顯然 ( 0 , 0 ) (0,0) (0,0) 先手必敗,我們將先手必敗節點稱為 奇異節點

可以發現奇異節點上下左右四個結點,以及右上和右下的兩個結點都不是奇異節點,

也就意味著如果 Alice 不在奇異節點上,那么 Alice 可以通過一步操作到達奇異節點,把奇異結點留給 Bob ,這樣 Bob 必敗,

我們可以發現 ( 1 , 2 ) , ( 3 , 5 ) (1,2),(3,5) (1,2),(3,5) 等等也都是奇異節點,

經過奇異節點的 3 3 3 條直線上的點,都能通過一步到達奇異節點,

發現這就建立起了一個有向圖的核的模型,

考慮引入 Beatty定理

如果兩個無理數 a , b a,b a,b 滿足:

1 a + 1 b = 1 \cfrac{1}{a}+\cfrac{1}{b}=1 a1?+b1?=1

那么對于兩個集合 A , B A,B A,B

A = { ? n a ? } , B = { ? n b ? } , n ∈ Z A=\begin{Bmatrix}\lfloor na\rfloor \end{Bmatrix},B=\begin{Bmatrix}\lfloor nb\rfloor \end{Bmatrix},n\in Z A={?na??},B={?nb??},nZ

有下面兩個結論:

A ∩ B = ? , A ∪ B = N + A\cap B=\varnothing,A\cup B=N^+ AB=?,AB=N+ (結論證明)

打表 發現 B i ? A i = i B_i?A_i=i Bi??Ai?=i

可得 b = a + 1 b=a+1 b=a+1 ,帶入 1 a + 1 b = 1 \cfrac{1}{a}+\cfrac{1}{b}=1 a1?+b1?=1 解得 a = 5 + 1 2 , b = 3 ? 5 2 a=\cfrac{\sqrt{5}+1}{2},b=\cfrac{3-\sqrt{5}}{2} a=25 ?+1?,b=23?5 ??

最終得出威佐夫博弈結論:假設兩堆石子為 ( a , b ) (a,b) (a,b)(其中 a < b a<b a<b

那么先手必敗,當且僅當 ( b ? a ) × ( 5 + 1 ) 2 = a (b-a)\times \cfrac{(\sqrt{5}+1)}{2}=a (b?a)×2(5 ?+1)?=a

其中的 ( 5 + 1 ) 2 \cfrac{(\sqrt{5}+1)}{2} 2(5 ?+1)? 實際就是黃金分割數 1.618 1.618 1.618,細思極恐,細思極恐…

Code

int main() {
	scanf("%d%d", &n, &m);
    if (a > b)
        swap(a, b);
    int ans = (b - a) * ((1.0 + sqrt(5.0)) / 2.0);
    if (ans == a)
        puts("0");
    else
        puts("1");
    return 0;
}

Problem A Game of Taking Stones(2017 ACM ICPC dalian C)

給你兩個石堆的石頭數量 a , b a,b a,b,兩個人輪流拿,兩人輪流從任意一堆取至少一個或者從兩堆取同樣多的物品,問你先手獲勝還是后手勝,

a , b ≤ 1 0 100 a,b\le10^{100} a,b10100

威佐夫博弈模板題,但是資料開到了 1 0 100 10^{100} 10100,普通的C++高精會炸,所以直接用Java就行了(而且Java比C++高精好寫多了 ~ )

我們直接用 Java 二分求出 5 \sqrt{5} 5 ?,設 b > a b>a b>a 計算 ( b ? a ) × ( 5 + 1 ) 2 \cfrac{(b-a)\times (\sqrt{5}+1)}{2} 2(b?a)×(5 ?+1)? 即可,

Code

import java.math.*;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        BigDecimal one = BigDecimal.valueOf(1);
        BigDecimal two = BigDecimal.valueOf(2), five = BigDecimal.valueOf(5);
        BigDecimal t = one.add(sqrt(five, 500)).divide(two);
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()) {
            BigDecimal a, b, tmp = null;
            a = sc.nextBigDecimal();
            b = sc.nextBigDecimal();

            if (a.compareTo(b) > 0) {
                tmp = a;
                a = b;
                b = tmp;
            }

            if (b.subtract(a).multiply(t).setScale(0, BigDecimal.ROUND_DOWN).equals(a)) {
                System.out.println(0);
            } else
                System.out.println(1);

        }

        sc.close();
    }

    private static BigDecimal sqrt(BigDecimal x, int n) {
        BigDecimal l = BigDecimal.ZERO, r = x, mid;
        BigDecimal two = BigDecimal.valueOf(2);

        for (int i = 0; i <= n; i++) {
            mid = l.add(r).divide(two);

            if (mid.pow(2).compareTo(x) <= 0)
                l = mid;
            else
                r = mid;
        }

        return l;
    }
}

0x14 斐波那契博弈 F i b o n a c c i G a m e \tt Fibonacci\ Game Fibonacci Game

待更…

0x20 SG函式

0x21 前置知識: M e x Mex Mex 運算

S S S 表示一個非負整數集合,定義 m e x ( S ) mex(S) mex(S) 為求出不屬于集合S的最小非負整數的運算,即:

m e x ( S ) = m i n { x } mex(S) = min\{x\} mex(S)=min{x} x x x 屬于自然數,且 x x x 不屬于 S S S

0x22 SG函式

SG函式是對游戲圖中每一個節點的評估函式,

規定游戲終點的 SG 函式值定為 0 0 0,即 S G ( 終 點 ) = 0 SG(終點)=0 SG()=0

在有向圖游戲中(任何一個博弈都可以轉換為一個有向圖游戲),對于每個節點 x x x (局面),設從 x x x 出發共有 k k k 條有向邊(合法的操作),分別到達節點 y 1 , y 2 , … , y k y_1, y_2, …, y_k y1?,y2?,,yk?(下一個局面) ,定義 S G ( x ) SG(x) SG(x) x x x后繼節點(注意只是一層的后繼結點) y 1 , y 2 , … , y k y_1, y_2, …, y_k y1?,y2?,,yk? S G SG SG 函式值構成的集合再執行 m e x ( S ) mex(S) mex(S) 運算的結果,即:

S G ( x ) = m e x ( { S G ( y 1 ) , S G ( y 2 ) , … , S G ( y k ) } ) SG(x) = mex(\{SG(y1), SG(y2), …, SG(yk)\}) SG(x)=mex({SG(y1),SG(y2),,SG(yk)})

如 圖20.1 所示:


圖20.1

%2

特別地,整個有向圖游戲 G G G S G SG SG 函式值被定義為有向圖游戲起點 s s s S G SG SG 函式值,即 S G ( G ) = S G ( s ) SG(G) = SG(s) SG(G)=SG(s)

我們發現若 S G ( x ) = 0 SG(x)=0 SG(x)=0 則為必敗狀態,若 S G ( x ) =? 0 SG(x)\not= 0 SG(x)?=0,則為必勝狀態,(若非零說明這個點直接指向了 0 0 0,也就意味著可以到達必敗狀態,是必勝狀態)

0x23 SG 函式的性質

兩個SG函式的性質:

(1)對于任意的局面,如果它的 S G SG SG 值為 0 0 0 ,那么它的任何一個后
繼局面的SG值不為 0 0 0

(2)對于任意的局面,如果它的 S G SG SG 值不為 0 0 0 ,那么它一定有一個
后繼局面的 S G SG SG 值為 0 0 0

SG( S p r a g u e ? G r u n d y \tt Sprague-Grundy Sprague?Grundy)定理 :所有一般勝利下的公平組合游戲都能轉化成尼姆數表達的尼姆堆博弈,一個博弈的 尼姆值 定義為這個博弈的等價尼姆數,即:對于當前游戲 X X X,它可以拆分成若干個子游戲 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1?,x2?,...,xn? 那么 S G ( X ) = S G ( x 1 ) ⊕ S G ( x 2 ) ⊕ . . . ⊕ S G ( x n ) SG(X)=SG(x_1)\oplus SG(x_2)\oplus...\oplus SG(x_n) SG(X)=SG(x1?)SG(x2?)...SG(xn?)

對于由 n n n 個有向圖游戲組成的組合游戲 設它們的起點分別為 s 1 , s 2 , . . . , s n s_1,s_2,...,s_n s1?,s2?,...,sn?(好多個起點,有好多個博弈圖,也就是有好多個 圖20.1 ) ,則當且僅當 S G ( s 1 ) ⊕ S G ( s 2 ) ⊕ . . . ⊕ S G ( s n ) =? 0 SG(s_1)\oplus SG(s_2)\oplus...\oplus SG(s_n)\not=0 SG(s1?)SG(s2?)...SG(sn?)?=0 時,這個游戲為先手必勝

也就意味著,我們將原本需要考慮博弈圖的所有點,復雜度較高,但是我們通過SG函式,變成了只需要考慮起點即可,

證明方法類似尼姆游戲,略,

0x24 轉換為 Nim 游戲

事實上,每一個簡單SG-組合游戲都可以完全等效成一堆數目為 K K K 的石子(Nim 游戲),其中 K K K 為該簡單游戲的 S G SG SG 函式值,這樣的等效是充要的,

定義游戲的和: 考慮任意多個同時進行的SG-組合游戲,這些SG-組合游
戲的和是這樣一個SG-組合游戲,在它進行的程序中,游戲者可以任意
挑選其中的一個 單一游戲 進行決策,最終,沒有辦法進行決策的人輸,

定理 23.1: 在我們每次只能進行一步操作的情況下,對于任何的游戲的和,我們若將其中的任一單一SG-組合游戲換成數目為它的SG值的一堆石子, 該單一SG-組合游戲的規則變成取石子游戲的規則(可以任意取,甚至 取完),則游戲的和的勝負情況不變,

這個定理告訴我們,在考慮游戲的和時,每一個單一游戲的具體細節是可以被忽略的,我們所關心的只是SG函式值,所以我們可以將組成它的所有子游戲全部換成相應數目的一堆石子,這樣,所有的游戲的和都等價成一個 Nim 游戲,

0x24 有向圖游戲的和

G 1 , G 2 , … , G m G_1, G_2, …, G_m G1?,G2?,,Gm? m m m 個有向圖游戲,定義有向圖游戲 G G G ,它的行動規則是任選某個有向圖游戲 G i G_i Gi? ,并在 G i G_i Gi? 上行動一步, G G G 被稱為有向圖游戲 G 1 , G 2 , … , G m G_1, G_2, …, G_m G1?,G2?,,Gm?的和,

有向圖游戲的和的 S G SG SG 函式值等于它包含的各個子游戲 S G SG SG 函式值的異或和,即:

S G ( G ) = S G ( G 1 ) ⊕ S G ( G 2 ) ⊕ … ⊕ S G ( G m ) SG(G) = SG(G_1) \oplus SG(G_2)\oplus …\oplus SG(G_m) SG(G)=SG(G1?)SG(G2?)SG(Gm?)

定理22.1: 有向圖游戲的某個局面必勝,當且僅當該局面對應節點的SG函式值大于0,

定理22.2: 有向圖游戲的某個局面必敗,當且僅當該局面對應節點的SG函式值等于0,

我們只需要判斷一下 S G ( G ) SG(G) SG(G) 即可,


Problem A 集合- Nim游戲( AcWing 893)

給定 n n n 堆石子以及一個由 k k k 個不同正整數構成的數字集合 S S S

現在有兩位玩家輪流操作,每次操作可以從任意一堆石子中拿取石子,每次拿取的石子數量必須包含于集合 S S S ,最后無法進行操作的人視為失敗,

問如果兩人都采用最優策略,先手是否必勝,

每一堆輸入的石子數就是每一堆的起點,答案就是所有起點的 Nim 和

假設某一堆有 10 10 10 個石子, S = { 2 , 5 } S=\{2,5\} S={2,5} 那么博弈圖就是從 10 10 10 開始連邊,如圖20.1 所示,


圖20.2

本題的連邊方式就是從集合 S S S 中選擇一個數往下走(取走這么多數,往下搜 x ? s u m x-sum x?sum

我們直接記憶化搜索sg函式即可

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
#include <unordered_set>
#include <cstring>

using namespace std;
const int N = 507, M = 50007;
typedef long long ll;
typedef int itn;

itn n, m;
int a[N];
itn s[N], f[M];

int sg(int x)//記憶化搜索
{
    if(f[x] != -1) return f[x];
    
    unordered_set<int>S;
    for(int i = 1; i <= m; ++ i) {
        itn sum = s[i];
        if(x >= sum) S.insert(sg(x - sum));
    }
    for(int i = 0; ; ++ i) {
        if(!S.count(i))
        return f[x] = i;
    }
}

int main()
{
    scanf("%d", &m);
    for(int i = 1; i <= m; ++ i) {// m 個起點
        scanf("%d", &s[i]);
    }
    int res = 0;
    scanf("%d", &n);
    memset(f, -1, sizeof f);
    for(int i = 1; i <= n; ++ i) {
        int x;
        scanf("%d", &x);
        res ^= sg(x);
    }
    
    if(res == 0) puts("No");
    else puts("Yes");
    return 0;
}

以下為待更內容,預計將在 2021/2/21 前更完 (●ˇ?ˇ●)

0x30 SG游戲及其拓展變形

0x 31 Anti-SG 游戲(走完最后一步者輸)

Anti-Nim游戲

n n n 堆石子,兩個人可以從任意一堆石子中拿任意多個石子(不能不拿),拿走最后一個石子的人失敗,問誰會勝利


看上去好像顛覆了SG游戲的規則,連勝利的條件都反了這怎么玩?

先給出結論

先手必勝當且僅當:

(1) ? \forall ? 所有堆的石子數都為 1 1 1 且游戲的SG值為 0 0 0

(2) ? \exist ? 有些堆的石子數大于 1 1 1 且游戲的SG值不為 0 0 0

考慮證明:


游戲大概可以被分為3種情況

  • 每堆只有一個石子

當異或值(SG值)為 0 0 0 時(有奇數堆),先手必勝
當異或值(SG值)不為 0 0 0 時(有偶數堆),先手必敗

  • 只有一堆石子數大于1,先手必勝

經過分析不難發現,先手可以對數量大于1的那堆石子下手腳,從而構造出后手必敗的狀態

存在至少兩堆石子數大于1
當異或和為0時,先手必敗
當異或和不為0時,先手必敗
這一步的結論與Nim游戲非常相似,同時它們的證明也非常相似,大概就是從異或和為0的狀態無論怎樣都會變為異或和不為0的狀態,反過來從異或和不為0的狀態總有一步能到達異或和為0的狀態

0x32 SJ定理

0x33 Multi-SG游戲(可以將一堆石子分成多堆)

0x34 Every-SG游戲(每一個可以移動的棋子都要移動)

0x35翻硬幣游戲

0x36 無向圖刪邊游戲

0x40 經典組合游戲拓展

0x41 巴什博奕的擴展——k倍動態減法游戲

0x42 尼姆博弈的三種擴展

0x50 尋找必敗態解題

0x60 不平等博弈問題

0x70 更多例題

Problem A Euclid’s Game(POJ 1063 )

給定兩個正整數 a , b a,b a,b,每次操作,可以將大的數減掉小的數的整數倍,當一個數變為 0 0 0 的時候結束,先將其中一個數減為 0 0 0 的獲勝,Stan先手,問誰能贏,

Solution

把問題轉化成我們熟悉的模型,相當于有一排石子堆,必須把前面的石子堆取完了才能取后面的,取最后一個石子的人贏,問誰能贏


  • 博弈論知識匯總

  • 博弈論合集(博弈)

  • 博弈論全家桶

  • 博弈論題目總結(一)——簡單組合游戲

  • 博弈論題目總結(二)——SG組合游戲及變形

  • 博弈論入門之威佐夫博弈

  • 博弈論進階之Anti-SG游戲與SJ定理

  • 博弈論總結

  • 《淺談如何解決不平等博弈問題》 方展鵬

  • 《從“k倍動態減法游戲”出發探究一類組合游戲問題》曹欽翔

  • 《組合游戲略述——淺談SG游戲的若干拓展及變形》賈志豪

  • acm中的一些博弈論知識

  • ACM-ICPC中博弈論的一些小小總結

  • 尋找必敗態——一類博弈問題的快速解法

  • 運籌學基礎教程(第二版)第9章 對策(博弈)論.ppt

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/261811.html

標籤:其他

上一篇:魔改部署自己專屬的合成大西瓜(二:魔改篇)

下一篇:演算法初探系列3 -深度優先搜索之剪枝策略

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more