哼哼唧唧學博弈

一、巴什博奕(同餘理論)
一堆物品 n個 每人能取出1~m個 甲先拿 乙後拿
若n=m+1 乙勝
若n=k*(m+1) 乙勝
若n=k*(m+1)+r 甲勝

1.#include<iostream>   
2.using namespace std;   
3.int main()   
4.{   
5.    int cas,total,price;   
6.    scanf("%d",&cas);   
7.    while(cas--)   
8.    {   
9.        scanf("%d%d",&total,&price);   
10.        if(total%(price+1))   
11.            cout<<"先手贏"<<endl;   
12.        else   
13.            cout<<"先手輸"<<endl;   
14.    }   
15.    return 0;   
16.}   

二、威佐夫博弈(黃金分割)
有兩堆各若干個物品,兩個人輪流從某一堆或同時從兩堆中取同樣多的物品,規定每次至少取一個,多者不限,最後取光者得勝。

首先介紹一下奇異局勢。
甲乙來拿石子,我們用(ak,bk)(ak ≤ bk ,k=0,1,2,…,n)表示兩堆物品的數量並稱其爲局勢,如果甲面對(0,0),那麼甲已經輸了,這種局勢我們稱爲奇異局勢。前幾個奇異局勢是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。
可以看出,a0=b0=0,ak是未在前面出現過的最小自然數,而 bk= ak + k。
奇異局勢的性質有三條:
1.任何自然數都包含在一個且僅有一個奇異局勢中。
2.任意操作可將奇異局勢轉變爲非奇異局勢。
3.可以採取操作將非奇異局勢轉變爲奇異局勢。

所以威佐夫博弈中必贏一方的理論就是始終讓對手面對必輸局(奇異局)。

結論:
面對非奇異局勢,先拿者必勝;面對奇異局勢,後拿者必勝。
奇異局勢判斷方法:
求出兩個石子堆的差值,判斷差值與黃金分割率的乘積是否與大的石子堆數目相等。

方法證明:
ak =[k(1+√5)/2]→方括號表示取整函數,bk= ak + k (k=0,1,2,…n )
奇妙的是其中出現了黃金分割數(1+√5)/2 = 1.618…,因此,由ak,bk組成的矩形近似爲黃金矩形,由於2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那麼a = aj,bj = aj + j,若不等於,那麼a = aj+1,b = aj + j + 1,若都不是,那麼就不是奇異局勢。然後再按照上述法則進行,一定會遇到奇異局勢。

bool Wythoff(int n,int m)//兩堆石子數目
{
    if(n<m) swap(n,m);
    int k=n-m;
    n=(int)(k*(1+sqrt(5))/2.0);
    if(n==m)
        return 0;
    else
        return 1;
}

三、尼姆博弈(異或原理)
定義P-position和N-position,其中P代表Previous,N代表Next。
上一次move的人有必勝策略的局面是P- position,也就是“後手可保證必勝”或者“先手必敗”,
現在輪到move的人有必勝策略的局面是N-position,也就是“先手可保證必勝”。
更嚴謹的定義是:
1.無法進行任何移動的局面(也就是terminal position)是P-position;
2.可以移動到P-position的局面是N-position;
3.所有移動都導致N-position 的局面是P-position。

所以 可以來畫P-N圖,然後找規律,比如 hdu2147

對於一個Nim遊戲的局面(a1,a2,…,an),它是P-position當且僅當a1^a2^…^an=0,其中^表示異或(xor)運算。

判斷方法:
對每堆石子數異或,如果異或爲0,先手輸;否則,後手輸。

四、斐波那契博弈
講的蠻好
參考博客:
簡潔明瞭
題目與知識點相結合
值得多啃幾遍的SG函數

ps:感覺這幾天整個機房都在學博弈○| ̄|_

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