所有的博弈都是找到必敗態,
如果當前的狀態是必敗態那麼無論怎麼操作都無法使遊戲變成必勝態,
反之如果是必勝態則必然存在一步操作還使遊戲變成必勝態。
下面說的就是三種基本的博弈:巴什博弈
威佐夫博奕
尼姆博弈
一:巴什博弈
有一堆石子,石子個數為
n,兩人輪流從石子中取石子出來,最少取乙個,最多取
m個。最後不能取的人輸,問你最後的輸贏情況。
這種就是可以直接判斷必敗態的問題。如果這堆石子少於或者等於
m個,那麼先手贏。如果石子數目為
m+1個,那麼先手必輸,因為無論先手怎麼拿石子,後手都可以直接把剩下的石子全部拿走。如果石子數目為
m+1那麼先手就可以拿走
n-(m+1)
個石子,使得對手面對
m+1的必敗態,這樣先手必贏。所以如此推算下去,我們就知道當
n%(m+1)==0
時,先手輸,否則先手贏。則n*
(m+1
)為必敗態。先手取
x,另外乙個人就可以取
y,使得取的石子的總數是
m+1。
有兩堆石子,石子數目分別為n和m,現在兩個人輪流從兩堆石子中拿石子,每次拿時可以從一堆石子中拿走若干個,也可以從兩中拿走相同數量的石子,拿走最後一刻石子的人贏。
可以發現,前面幾組奇異局勢為(a,b) :(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)
這其中第k組的a為前面沒有出現過的最小非負整數,而b = a + k
兩個人如果都採用正確操作,那麼面對非奇異局勢,先拿者必勝;反之,則後拿者取勝。
那麼任給乙個局勢(a,b),怎樣判斷它是不是奇異局勢呢?我們有如下公式:
ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,...n 方括號表示取整函式)
題目大意:威佐夫博奕
[cpp]view plain
copy
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi acos(-1.0)
#define maxn 1000
#define inf 1<<25
#define mem(a, b) memset(a, b, sizeof(a))
typedef
long
long
ll;
using
namespace
std;
intmain ()
return
0;
}
同樣是取石頭問題,不過如果先手能贏,要輸出第一次取石子後所剩的情況。(如果在任意的一堆中取走石子能勝同時在兩堆中同時取走相同數量的石子也能勝,先輸出取走相同數量的石子的情況)
這道題目要輸出威佐夫博弈從非奇異局勢到奇異局勢的轉變方案。比直接判斷複雜了很多,其實資料量不大,可以打表。不過還是採用推理的方式來解這道題。
思考過程:
判斷從一堆中取出石頭,這裡其實可以分為三種。假設一開始的時候為(a,b) (b>a) 即預設括號裡面第二個數大於第乙個數 。第一種是從b當中取走少量的,變為(a,b - k)。第二種是從b中取走大量的,變為(b - t, a)。第三種是從a當中取走一些,變為(a - t,b)
[cpp]view plain
copy
// 威佐夫博弈 + 輸出方案
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi acos(-1.0)
#define maxn 1000
#define inf 1<<25
#define mem(a, b) memset(a, b, sizeof(a))
typedef
long
long
ll;
using
namespace
std;
intmain ()
} } return
0;
}
定義:有三堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。
當剩下一堆石頭時,一定是必勝態。當剩下兩堆相同的石頭時(n,n),一定是必敗態。只要你取x,對手在另一堆裡面取x,會得到(n - x,n - x)。至於三堆的就比較麻煩,可以知道(1,2,3)是必敗態。
不過最後有個神奇的結論,就是當每堆石頭取異或之後,不為0代表著必勝態。為0代表著必敗態。
證明:
1、最後的狀態,全為零,顯然成立;
2、對於某個局面(a1,a2,...,an),若a1^a2^...^an<>0,一定存在某個合法的移動,將ai改變成ai'後滿足a1^a2^...^ai'^...^an=0。不妨設a1^a2^...^an=k,則一定存在某個ai,它的二進位制表示在k的最高位上是1(否則k的最高位那個1是怎麼得到的)。這時ai^k3、對於某個局面(a1,a2,...,an),若a1^a2^...^an=0,一定不存在某個合法的移動,將ai改變成ai'後滿足a1^a2^...^ai'^...^an=0。因為異或運算滿足消去率,由a1^a2^...^an=a1^a2^...^ai'^...^an可以得到ai=ai'。所以將ai改變成ai'不是乙個合法的移動。證畢。
參考資料
題目大意:給你n堆石子,每堆個數不同,兩個人輪流從任意一堆當中取任意個石子。當其中乙個人取走最後一堆石頭時,獲勝。問先手能不能獲勝。如果能夠獲勝,求出能夠獲勝第一次取石子的情況。(a,b) a為該堆石頭數,b為取完之後的數。
[cpp]view plain
copy
/* 尼姆博奕 並且求輸出方案
*/#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi acos(-1.0)
#define maxn 200000
#define inf 1<<25
#define mem(a, b) memset(a, b, sizeof(a))
typedef
long
long
ll;
using
namespace
std;
intsg[maxn+10];
intmain ()
if(!sum) puts(
"no"
);
else
} } return
0; }
博弈(尼姆,威佐夫 巴什)
一堆n個物品,兩個人輪流從這堆物品中取物,規定每次至少取乙個,最多取m個。最後取光者得勝。先手必勝為1 有兩種情況 盡可能避免剩餘 m讓自己輸的情況。那麼 n 0時,取的人必輸,n 1 m時,取的人必贏 n m 1時,取的人必輸0 我們讓下乙個取的人到必輸0狀態,那麼自己就是必勝1狀態 只要下一步能...
巴什博弈 威佐夫博弈 nim博弈 斐波那契博弈
1.巴什博弈 一堆 n個物品 最多拿m個 最少拿 1個 include int main int argc,char argv return 0 2.威佐夫博弈 兩堆物品 最多拿一堆 最少拿 乙個 include include includeint x sqrt 5 1 2 int main in...
尼姆博弈 威佐夫博奕
尼姆博弈 有三堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。這種情況最有意思,它與二進位制有密切關係,我們用 a,b,c 表示某種局勢,首先 0,0,0 顯然是奇異局勢,無論誰面對奇異局勢,都必然失敗。第二種奇異局勢是 0,n,n 只要與對手拿走一樣...