哼哼唧唧学博弈

一、巴什博奕(同余理论)
一堆物品 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:感觉这几天整个机房都在学博弈○| ̄|_

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