日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」

發布時間:2023/12/15 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

博弈論基礎

博弈論又被稱為對策論(Game Theory),既是現代數學的一個新分支,也是運籌學的一個重要學科。博弈論主要研究公式化了的激勵結構間的相互作用,是研究具有斗爭或競爭性質現象的數學理論和方法。博弈論考慮游戲中的個體的預測行為和實際行為,并研究它們的優化策略。

引入:囚徒困境

囚徒困境的故事講的是,兩個嫌疑犯小A、小B作案后被警察抓住,分別關在不同的屋子里接受審訊。警察知道兩人有罪,但缺乏足夠的證據。警察告訴每個人:如果兩人都抵賴,各判刑一年;如果兩人都坦白,各判五年;如果兩人中一個坦白而另一個抵賴,坦白的放出去,抵賴的判十年。

于是,每個囚徒都面臨兩種選擇:坦白或抵賴。

在不和小B商量的情況下,作為小A的你是選擇招供坐牢5年或0年,還是會選擇抵賴坐牢10年或1年呢?

一般的人都會選著保險一點的招供吧。

反觀小B,也一定會做出同樣的選擇,也就是招供。換句話說,只要兩名囚徒都是自私且理性的,那么雙方都會同時選擇招供,結果就是雙方各判5年。

在這個場景中,雙方都無法單方面改變自己的博弈策略(單方面改變只會讓自己蒙受損失),使得局面進入了一個微妙而又穩定的平衡,這個平衡被稱為納什均衡

在現實中,也有很多類似的現象,比如家長給孩子報越來越多的課外班,比如高三考生備戰高考,卷起來了啊.從局外人看來,許多競爭都是顯而易見雙輸的局面,但是我們沒有辦法,因為我們都是參與博弈的“囚徒”。

ICG博弈

所討論的博弈問題滿足以下條件:

玩家只有兩個人,輪流做出決策。

游戲的狀態集有限,保證游戲在有限步后結束,這樣必然會產生不能操作者,其輸。

對任何一種局面,勝負只決定于局面本身,而與輪到哪位選手無關。

取石子游戲:取石子游戲是一個古老的博弈游戲,發源于中國,它是組合數學領域的一個經典問題。它有許多不同的玩法,基本上是兩個玩家,玩的形式是輪流抓石子,勝利的標準是抓走最后的石子。玩家設定:先取石子的是玩家A(先手A),后取石子的是玩家B(后手B)。

經典的三種玩法

一、巴什博奕(Bash Game)

二、尼姆博奕(Nimm Game)

三、威佐夫博奕(Wythoff Game)

(一)巴什博弈

1堆n個石子每次最多取m個、至少取1個

Case 1:如果n=m+1,那么由于一次最多只能取m個,所以,無論先取者拿走多少個,后取者都能夠一次拿走剩余的物品,后者取勝。

Case 2:n=(m+1)*r+s,(r為任意自然數,s≤m),那么先取者要拿走s個物品,如果后者拿走k(1≤k≤m)個,那么先取者再拿走m+1-k個,結果剩下(m+1)(r-1)個,以后保持這樣的取法,那么先取者肯定獲勝。

Case 3:n=r*(m+1),先手拿走k(1≤k≤m)個,那么后手再拿走m+1-k個,結果剩下(m+1)(r-1)個,以后保持這樣的取法,則后手勝,先手必敗。

總之,要保持給對手留下(m+1)的倍數,就能最后獲勝。

術語:正經人稱(m+1)的局面為奇異局勢

變相的玩法

兩個人輪流報數,每次至少報一個,最多報十個,誰能報到100者勝。(等價于從一堆100個石子中取石子,最后取完的勝)

例題:2368 — Buttons (poj.org)

題面:

題面意思:有一堆k個的石頭,每人輪流拿1,2,..L個石頭,數據范圍是3 <= K <= 100 000 000 ,2 <= L < K。輸入k的值,要求輸出最小的L,使得后者勝。

在理解了巴什博弈之后來看這題還是思路比較清晰的,首先想讓后手勝,就必須把(1+L)的局面留給先手。這題沒問我們誰會贏,問的是后手要贏的最小L值為多少。那我們就找到能被k整除的最小大于2的因數,之后減1輸出就是答案了。

于是有了以下代碼注意下(poj用不了萬能頭文件,編譯器要求有點嚴格。):

//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=100005;
ll n;//石子數量
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    ll i;
    for(i=2;i<n;i++)//依次找最小的因子
    {
        if(n%(i+1)==0)
        {
            cout<<i<<endl;
            break;
        }
    }
    if(i==n) cout<<0<<endl;//找不到的情況下輸出0
    return 0;
}

就是說數據范圍1e8,就超時快樂,TEL了哈哈哈哈哈哈。由于循環2~n,時間復雜度是O(n)。

再有一個新的思路就是,遍歷一遍所有的n的因數,存起來,在輸出最小大于等于3的因數減一。一下代碼時間復雜度為O(log n)。AC快樂。

//#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll n,a[N];//n為石頭總數,a[i]存n的因數
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    int temp=0;
    for(int i=1;i*i<=n;i++)
    {
        if(n%i==0&&i*i!=n) a[temp++]=i,a[temp++]=n/i;
        //注意要區別開類似n=4時,因數為1,2,4.而不是1,2,2,4的情況
        else if(n%i==0&&i*i==n) a[temp++]=i;
    }
    sort(a,a+temp);//從小到大排序一下
    for(int i=0;i<temp;i++)
    {
        if(a[i]>=3)//找到最小大于等于3的因數,減一輸出
        {
            cout<<a[i]-1<<endl;
            break;
        }
    }
    return 0;
}

(二)尼姆博弈

有n堆石子,每堆石子的數量是a1,a2,a3……,二個人依次從這些石子堆中的一個拿取任意的石子,至少一個,最后一個拿光石子的人勝利

n=1: 先手全拿,先手必勝。

n=2:有兩種情況,一種可能相同,一種情況一堆比另一堆少(多)

(m,m) 按照“有一學一,照貓畫貓”法,先手必輸。

(m,M)先手先從多的一堆中拿出(M-m)個,此時后手面對(m,m)的局面先手必勝。

術語:正經人稱(m,m)的局面為奇異局勢

n=3:(m,m,M)先手必勝局,先手可以先拿M,之后變成了(m,m,0)的局面,是不是很熟悉~

(a1,a2,a3)的話,舉個例子(1,2,3),先手取完之后可能的局面為(0,2,3),(1,1,3),(1,0,3),(1,2,2),(1,2,1),(1,2,0)都是之前講過的,情況如下:

前人告訴我們的規律是:異或的結果均為0

獲勝情況的討論

面對異或結果為0的玩家必輸。

結果不為0,則玩家有獲勝的取法。

例題:891. Nim游戲 – AcWing題庫

題面:

看懂了尼姆博奕,這個題目就是分分鐘AC咯。

上代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll n,a[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    int ans=a[0];
    for(int i=1;i<n;i++) ans^=a[i];//^就是做異或運算
    if(ans==0) cout<<"No"<<endl;
    else cout<<"Yes"<<endl;
    return 0;
}

(三)威佐夫博弈

有兩堆各若干個物品,兩個人輪流從任一堆取至少一個或同時從兩堆中取同樣多的物品,規定每次至少取一個,多者不限,最后取光者得勝。

舉一個例子:局勢是(1,2),先手有四種取法,動動你聰明的腦子就會發現無論先手怎么取,后手都能勝利,也就是說(1,2)是奇異局勢。

沒腦子的人來看看分析咯:

先手從第一堆里面拿1個,后者拿光后面的2個,后者勝。

先手從第一堆和第二堆里面同時拿1個,后者只能拿走第二堆剩下的1個,后者勝。

先手從第二堆里面拿2個,后手拿走第一堆的1個,后者勝.

先手從第二堆里面拿1個,后手從第一堆和第二堆里面同時拿走1個,后者勝。

假設現在的局勢是(3,5):

(1)先手在“3”中取1個,后手就可以在“5”中取走4個,這樣就變成了(1,2)的局勢

(2)先手在“3”中取2個,后手就可以在 “5” 中取走3個,這樣也變成了(1,2)的局勢

(3)先手在“5”中取1個,后手就在 “3”和“5” 中各取走2個,這樣成了(1,2)的局勢

(4)先手在”5”中取2個,后手就在 “3”和”5”中各取走3個,這樣變成了(0,0)的局勢,先手輸

(5)先手在“5”中取3個,后手就在 “3”和“5” 中各取走1個,也變成了(1,2)的局勢

(6)先手在“5”中取4個,后手在“3”中取走1個,還是(1,2)的局勢

我們可以來找找那些先手必輸局勢的規律(奇異局勢)

  • 第一種(0,0)
  • 第二種(1,2)
  • 第三種(3,5)
  • 第四種 (4 ,7)
  • 第五種(6,10)
  • 第六種 (8,13)
  • 第七種 (9 ,15)
  • 第八種 (11 ,18)
  • 第n種(a,b)

我們會發現他們的差值是遞增的,分別是0,1,2,3,4,5,6,7……n

還有一個規律(正常人都發現不了):a=(b-a)*1.618向下取整

就是:a = int(b – a)*1.618

注:這里的int是強制類型轉換,注意這不是簡單的四舍五入,假如后面的值是3.9,轉換以后得到的不是4而是3,也就是說強制int類型轉換得到的是不大于這個數值的最大整數。

有些題目要求精度較高,我們可以用下述式子來表示這個值:

1.618 = (sqrt(5.0) + 1) / 2

頭文件:include<math.h>

例題:1067 — 取石子游戲 (poj.org)

題面:

代碼:

//#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll a,b;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(cin>>a>>b)//多組輸入!!!
    {
        double flag= (sqrt(5.0) + 1) / 2.0;//精度高一些用double來存1.618
        if(a>b) swap(a,b);//保證b要比a大,后面有用到b-a
        if(a==int((b-a)*flag))cout<<0<<endl;//先手面對奇異局勢必輸
        else cout<<1<<endl;
    }

    return 0;
}

總結

以上是生活随笔為你收集整理的数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。