LeetCode 292. Nim遊戲
題目描述:
你和你的朋友,兩個人一起玩ofollow,noindex">Nim遊戲 :桌子上有一堆石頭,每次你們輪流拿掉 1 - 3 塊石頭。 拿掉最後一塊石頭的人就是獲勝者。你作為先手。
你們是聰明人,每一步都是最優解。 編寫一個函式,來判斷你是否可以在給定石頭數量的情況下贏得遊戲。
示例:
輸入: 4 輸出: false 解釋: 如果堆中有 4 塊石頭,那麼你永遠不會贏得比賽; 因為無論你拿走 1 塊、2 塊 還是 3 塊石頭,最後一塊石頭總是會被你的朋友拿走。
思路
簡單題,巴什博弈 。
顯然,如果n=m+1,那麼由於一次最多隻能取m個,所以,無論先取者拿走多少個,後取者都能夠一次拿走剩餘的物品,後者取勝。因此我們發現瞭如何取勝的法則:如果n=(m+1)r+s,(r為任意自然數,s≤m),那麼先取者要拿走s個物品,如果後取者拿走k(≤m)個,那麼先取者再拿走m+1-k個,結果剩下(m+1)(r-1)個,以後保持這樣的取法,那麼先取者肯定獲勝。總之,要保持給對手留下(m+1)的倍數,就能最後獲勝。
對於巴什博弈,那麼我們規定,如果最後取光者輸,那麼又會如何呢?
(n-1)%(m+1)==0則後手勝利
先手會重新決定策略,所以不是簡單的相反行的
JAVA SOLUTION
class Solution { public boolean canWinNim(int n) { return n % 4 == 0 ? false : true; } }
擴充套件
威佐夫博奕
威佐夫博弈(Wythoff's game):有兩堆各若干個物品,兩個人輪流從任一堆取至少一個或同時從兩堆中取同樣多的物品,規定每次至少取一個,多者不限,最後取光者得勝。
兩個人如果都採用正確操作,那麼面對非奇異局勢,先拿者必勝;反之,則後拿者取勝。
那麼任給一個局勢, (a,b),怎樣判斷它是不是奇異局勢呢?我們有如下公式:
尼姆博奕
指的是這樣的一個博弈遊戲,目前有任意堆石子,每堆石子個數也是任意的,雙方輪流從中取出石子,規則如下:
1)每一步應取走至少一枚石子;每一步只能從某一堆中取走部分或全部石子;
2)如果誰取到最後一枚石子就勝。
判斷當前局勢是否為必勝(必敗)局勢:
把所有堆的石子數目用二進位制數表示出來,當全部這些數按位異或 結果為0時當前局面為必敗局面,否則為必勝局面;
#include<iostream> using namespace std; int temp[ 20 ]; //火柴的堆數 int main() { int i, n, min; while( cin >> n ) { for( i = 0; i < n; i++ ) cin >> temp[ i ]; //第i個火柴堆的數量 min = temp[ 0 ]; for( i = 1; i < n ; i++ ) min = min^temp[ i ]; //按位異或 if( min == 0 ) cout << "Lose" << endl; //輸 else cout << "Win" << endl; //贏 } return 0; }
斐波那契博弈
有一堆個數為n的石子,遊戲雙方輪流取石子,滿足:
1)先手不能在第一次把所有的石子取完;
2)之後每次可以取的石子數介於1到對手剛取的石子數的2倍之間(包含1和對手剛取的石子數的2倍)。
約定取走最後一個石子的人為贏家,求必敗態。
這個遊戲叫做斐波那契博弈,肯定和斐波那契數列
:
有密切的關係。如果試驗一番之後,可以猜測:先手勝當且僅當n不是斐波那契數。換句話說,必敗態構成斐波那契數列。