問題:
假設有兩堆石頭,有兩個玩家會根據如下的規則輪流取石頭:
每人每次可以從兩堆石頭中各取出數量相等的石頭,或者僅從一堆石頭中取出
任意數量的石頭;最後把剩下的石頭一次拿光的人獲勝。
請問在哪些局面(依
據兩堆石頭中的石頭個數)下,先取石頭的玩家有必勝的策略。
解法:類似構造質數的篩選方法,這裡我們利用找到的必輸局面(後取的玩家有必勝策略)
來篩去掉能通過一次操作達
該必輸局面的其它必勝局面(先取的玩家有必勝策略)。
最後選出的局面都是必輸局面。
構造必勝策略:
如果一開始的局面就是必輸局面,那麼可能先取的玩家沒有必勝策略(當然如果後取
的玩家不太聰明,先取的玩家依然有可能能贏)。如果一開始的局面不是必輸局面,
那麼先取的玩家一定有必勝策略,且必勝策略就是保證每次都將當前非必輸局面轉變
為必輸局面(後取的玩家必輸)。
#include #include #include using namespace std;
// filter method
#define maxn 10000
#define clear(a) memset((a), 0, sizeof(a))
char ns[maxn][maxn]; // 用於篩選出必輸局面
int v[maxn];// 儲存(ind,v[ind])的必輸局面對
int main()
}} cout << endl;
// 使用必勝策略
doelse if (a==0)
else if (a==b)
// 將非必輸局面(a,b)轉變為必輸局面(v[b],b)或(a,v[a])
else if (v[b] < a)
else
// 對方隨機選取
int select = rand()%3;
if (select == 0)
else if (select == 1)
else
}while (a>0 || b>0);
}}
程式設計之美 nim 3 的遞迴解法
程式設計之美1.13 nim 3 兩對石頭的遊戲 一種遞迴解法 package main import fmt 兩堆石頭,假定 n m type pair struct var mapsafe map pair bool func main func nim n,m int bool if n m ...
程式設計之美 1 12 nim 2
參考 有若干堆石頭,a,b分布依次取,一次只能選擇一堆,從這堆中選擇大於0的石頭,問 1,如果最後取光石頭的人獲勝,a在什麼情況下獲勝?2,如果最後取光石頭的人失敗,a在什麼情況下獲勝?1.在規則1下,先手獲勝的情況,在規則2下先手同樣獲勝 2.規則1和規則2的取法不一樣。設當石頭出現 1,1,1,...
程式設計之美 NIM遊戲與NIM擴充套件遊戲的討論及解
程式設計之美上面有個nim的遊戲,規則如下 有n堆石頭,兩個人輪流從中取,一次只能在一堆中取,至少取乙個,最多把這一堆取完,取得最後乙個石頭的人勝利,問誰有必勝策略。解 設這n堆石頭的個數分別是x1,x2 xn,設f x x1 x2 x3 xn。如果f x 0則後取的獲勝,否則,先取的獲勝。證明 如...