我喜歡遊戲,我知道有些遊戲無論我怎樣努力最後的結果一定是輸的,或者是無論怎樣玩我都是贏得,這樣的一類遊戲從一開始就知道結果的遊戲,一定會有一種數學方法去描述。
所謂的nim的博弈就是一種從一開始就知道勝負的遊戲。這是一種兩個人玩的遊戲,玩家雙方面對一堆硬幣(或者石頭或者豆粒)。(假設有k>=1堆硬幣,每堆分別有n1,
n2,n
3……n
kn1
,n2
,n3
……n
k枚硬幣。遊戲的目標就是取得最後一枚硬幣。每個玩家只能任選一堆去拿不少於1個硬幣。率先拿完所有硬幣的玩家獲勝。
我們來看其中的某種特殊情況:
首先是如果只有一堆,先手一下全拿完,先手必勝。第二種是有兩堆,數量為n1、n2,如果n1!=n2先手的策略就是拿多的那一堆,拿完後使得兩堆相等,這樣重複讓兩堆相等那麼肯定先手會贏;反之如果n1==n2先手必敗。
而如果是很多堆,或者是玩法並不是拿任意》=1的硬幣,而是規定硬幣的個數怎麼辦呢???
這裡我就不給出證明過程了,直接說結論和解題方法。
首先定義mex(minimal excludant)運算,這是施加於乙個集合的運算,表示最小的不屬於這個集合的非負整數。例如mex=3、mex=0、mex{}=0;
我們就可以定義一下sg(x) = mex這裡的後繼指的是存在x轉換成y的方法,即對於1堆硬幣來說原先有y個硬幣,能通過一次move得到y枚硬幣。sg(x)是對於乙個遊戲的子問題來說的,也就是其中一堆硬幣,最後我們需要算出所有的sg值,然後進行異或運算g(g1)g(g2)…^g(gn) = 0先手必敗,不為0先手必勝。
int f[maxn]
;// 可以取的石子個數 idx[1~n]
int sg[maxn]
;// 0 ~ n sg函式的值
int isin[maxn]
;// mex{}
void
getsg
(int n)
for(
int j =
0; j <= n; j++)}
}}
1.可選步數為1~m的連續整數,直接取模即可,sg(x) = x % (m+1) 這其實就是巴什博奕。
2.可選步數為任意步,sg(x) = x,這其實是nim博弈原型。
3.可選步數為一系列不連續的數,用getsg()計算,這是nim博弈變式。
小公尺oj
這道題是在堆的數量為2,只能拿斐波那契數的乙個特例。
**:
#include
using
namespace std;
typedef
long
long ll;
const
int maxn =
1e4+10;
int f[maxn]
;// 可以取的石子個數 idx[1~n]
int sg[maxn]
;// 0 ~ n sg函式的值
int isin[maxn]
;// mex{}
void
get_f()
}int
main()
else
}return0;
}
博弈論 Nim博弈
1.nim博弈的起源很早,至於歷史我們就不再說了,直接說它的使用場景。1 依舊是兩個人博弈,但是物品時n堆,每一堆有ai個。2 每個人可以挑選一堆取走若干個,但是不能不取。3 最先取完所有物品的人獲勝。4 結論 所以堆的物品的數量異或起來是0,先手必敗。2.乙個nim博弈的例項 nim博弈。乍一看這...
博弈論 博弈混合
給你乙個n m的棋盤,然後給你4種棋子,分別是 1.王 能橫著走,或者豎著走,或者斜著走,每次可以走1格 2.車 可以橫著走或者豎著走,每次可以走無數格 3.馬 走日字形,例如 如果現在在 1,1 可以走到 2,3 即先走一格直線,然後斜著走一格 4.王后 可以橫著走,或者豎著走,或者斜著走,每次可...
Nim博弈(博弈論)
1.題目 給定n堆石子,兩位玩家輪流操作,每次操作可以從任意一堆石子中拿走任意數量的石子 可以拿完,但不能不拿 最後無法進行操作的人視為失敗。問如果兩人都採用最優策略,先手是否必勝。思路 必勝狀態 a1 a2 an 0 可以走到某乙個必敗狀態 必敗狀態 a1 a2 an 0 走不到任何乙個必敗狀態 ...