bzoj 3895 取石子(博弈 記憶化搜尋)

2021-07-16 09:22:03 字數 1657 閱讀 2818

time limit: 1 sec  

memory limit: 512 mb

submit: 267  

solved: 130 [

submit][

status][

discuss]

alice和bob兩個好朋含友又開始玩取石子了。遊戲開始時,有n堆石子

排成一排,然後他們輪流操作(alice先手),每次操作時從下面的規則中任選乙個:

·從某堆石子中取走乙個

·合併任意兩堆石子

不能操作的人輸。alice想知道,她是否能有必勝策略。

第一行輸入t,表示資料組數。

對於每組測試資料,第一行讀入n。

接下來n個正整數a1,a2…an,表示每堆石子的數量。

對於每組測試資料,輸出一行。

輸出yes表示alice有必勝策略,輸出no表示alice沒有必勝策略。 2

31 1 2

23 4

32 3 5

yesno

no100%的資料滿足t<=100,  n<=50. ai<=1000

[ submit][

status][

discuss]

【題解】【博弈+記憶化搜尋】

【 假設每堆石子的數量都》1,

那麼我們定義運算元b為當前石子總數+當前堆數-1,

若b為奇數,則先手必勝,否則後手必勝】

【1.如果先手選擇合併兩堆石子,那麼每堆石子的個數依然大於1,tot變為奇數.】

【2.如果先手選擇從一堆石子數大於2的堆中拿走一枚石子,那麼同上每堆石子個數依然大於1,tot變為奇數。】 

【3.如果先手選擇從一堆石子數等於2的堆中拿走一枚石子,那麼後手可以合併剩下的1枚石子到任意乙個堆(堆數-1,石子數,先手依舊面臨偶數)。那樣tot的奇偶性不變,每堆石子的個數依然大於1. 那麼為什麼後手不會選擇把剩下的乙個取走呢?因為取走後堆數-1,石子數-1,這樣奇偶性就變了,就把必勝太留給了對手,博弈的兩個人一定是聰明的所以他不可能這麼選擇)】

【下面考慮含有1的情況:】

[1) 從石子數為1的堆裡取乙個;

2) 將兩堆石子數為1的堆合併;

3) 把石子數為1的堆與乙個石子數不為1的堆合併 ;

4) 從石子數不為1的堆裡取走乙個]

【共四種情況,記憶化搜尋。不過要記住一點:每組資料間不重置

#include#include#includeusing namespace std;

int n,t;

int f[110][100010];

int dfs(int a,int b)

int main()

if(b>0) b--;

if(dfs(a,b)==1) printf("yes\n");

else printf("no\n");

} }

BZOJ3895 取石子(博弈 記搜)

傳送門 我們可以通過石子的堆數和每一堆的個數計算出剩餘的運算元,顯然運算元為奇先手必勝,為偶先手必敗。若將 1的石子堆單獨考慮,對於若干堆 1的石子,運算元為 n i 1x i 那麼我們可以記f a b 表示有a堆 1的石子,1的石子運算元為b的狀態 1表示先手必勝,0表示先手必敗 然後進行記搜,對...

bzoj3895 取石子(博弈論,記憶化搜尋)

time limit 1 sec memory limit 512 mb submit 361 solved 177 submit status discuss alice和bob兩個好朋含友又開始玩取石子了。遊戲開始時,有n堆石子 排成一排,然後他們輪流操作 alice先手 每次操作時從下面的規則...

BZOJ 3895 取石子 SG函式 搜尋

有n堆石子 從某堆石子中取走乙個 合併任意兩堆石子 不能操作的人輸。100 的資料滿足t 100,n 50.ai 1000 容易發現基礎運算元 d sum a i n 1 沒有個數為1的堆還好說,有的話 好麻煩啊啊啊啊啊怎麼可能找規律 然後看題解,woc記憶化搜尋 f i,j 表示i個個數為1的堆,...