洛谷P3150 pb的遊戲(1)
題目背景
(原創)
有一天 pb和zs玩遊戲 你需要幫zs求出每局的勝敗情況
題目描述
遊戲規則是這樣的: 每次一個人可以對給出的數進行分割,將其割成兩個非零自然數,之後由另一個人選擇留下兩個數中的其中一個;之後由另一個人進行分割這個剩下的數,重復步驟……
當一個人無法對數進行分割的時候遊戲結束,另一個人獲勝
現在要你求出N次遊戲的勝敗
每局由pb先進行分割,如果pb贏輸出"pb wins" 如果zs贏輸出"zs wins"
註:雙方都是絕頂聰明的
輸入輸出格式
輸入格式:
第一行一個數N,表示數據組數
之後N行,每行一個數M,表示每局初始的數
輸出格式:
共N行,每行一串字符 表示遊戲結果
輸入輸出樣例
輸入樣例#1:5 1 3 7 20 5輸出樣例#1:
zs wins zs wins zs wins pb wins zs wins
說明
1<N<50 1<=m<=1000000000
題目詳解
這道題是洛谷博弈論專題的第一道入門題, 然而剛開始我是不會做的, 畢竟是道入門題, 我博弈論還沒入門呢.
這道題的做法就是: 如果m為偶數, 那麽先手贏(即pb), 如果m為奇數, 那麽後手贏(即zs).
<strong> 做法很簡單, 可是我們要知道怎麽做的</strong>
說實話我對於他們兩個都聰明絕頂, 都會按照最優策略來走很不感冒. 既然他們聰明絕頂, 那麽先手明知道m為奇數時自己會輸, 為什麽不灑脫一點走呢? 也許亂走出奇跡?
那我們來試試看. 當m = 13
時, 先手為什麽會輸. 前提是先手知道自己按照最優策略會輸(因為輪到他分時為奇數), 所以開始亂走.
先手:13 = 4 +9
後手:選4, 4 = 1 +3
先手:不得已選3, 3=1+2
後手:選2,2=1+1
後手贏
不服? 再來一把
先手:13=6+7 後手:選6,6=1+5 先手:選5,5=1+4 後手:選4,4=1+3 先手:3=1+2 後手:2=1+1 後手贏
經過了兩把測試, 我們不管先手怎麽走(亂走或所謂最優策略),只要他手裏是奇數,都不得不拆成奇數+偶數, 那麽後手只要選擇偶數, 他就可以把這個數化成m = n + 1
(後手的最優策略), 把奇數轉移給先手. 這樣經過若幹次轉移之後, 後手手裏一定會是2
,然後2 = 1 + 1
, 後手就贏了.
所以, 其實手裏是奇數的人是沒有勝算的, 所以這個狀態是必敗態. 而手裏是偶數的人是有必勝的可能的, 只有他才有最優策略而且只要他按照最優策略走, 他一定會贏, 因此這個狀態是必勝態. 當然, 如果他sa, 就可能將必勝態拱手讓人.
而理解這個博弈論問題的關鍵, 就是擁有偶數的策略: 每次減一. 因而可以再次將偶數態(必勝態)轉移過來.
事實上, 剛接觸此題時, 我對所謂絕頂聰明, 所謂最優策略很困惑, 兩個人博弈, 憑什麽說我走的是最佳策略結果卻輸了? 我是不是應該把所有走法都試一遍, 然後都輸給你才算我輸?
我的理解是: 必敗態從來沒有最佳策略, 博弈也不是雙方的博弈, 而是處在必勝態的那方和自己博弈. 而這場博弈, 由於絕頂聰明的前提, 是必勝的, 而我們要做的, 只是找出誰有跟自己博弈的機會.
感性理解一下:這個題無非就是判斷奇偶數
AC代碼如下
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n,a; 6 cin>>n; 7 for(int i=1;i<=n;++i) 8 { 9 cin>>a; 10 if(a%2==1) 11 cout<<"zs wins"<<endl; 12 else 13 cout<<"pb wins"<<endl; 14 } 15 return 0; 16 }
洛谷P3150 pb的遊戲(1)