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的堆,...