1. 程式人生 > >ACM PKU POJ 1740 解題報告 -- 男人八題之四

ACM PKU POJ 1740 解題報告 -- 男人八題之四

題意:小明和小紅參加一種新的取石子游戲。遊戲開始時有 n 堆石子,參與遊戲的兩個選手輪流取走和移動石子,遊戲從小明開始。在每一輪中,選手選擇一個至少有一顆石子的堆,從該堆石子中拿走至少一個石子。接著,該選手可以多次地從該堆中剩下的石子中把任意多的個石子移動到任意的堆中。當然,該選手也可以不移動任何石子。但是,必須注意,選手必須從該選中的堆中取起至少一塊石子。因此,隨著遊戲的進行,石子越來越少。當輪到某選手時,已經沒有石子可以取走時,該選手輸掉了遊戲。小明和小紅都極其聰明,總能以最優的策略進行遊戲。現在,給定堆數 n 和每一堆的石子數目,請問小明能在遊戲中否獲勝?

本題中的遊戲是一種 impartial game

,應用 Sprague-Grundy 定理,可以計算出一些必敗狀態,從而獲得關於一般必敗狀態的規律。不過,本文打算就題論題,而不涉及較深的博弈理論。

先從 n = 1 開始考慮。這時,小明可以把該堆的所以石子取走,從而必勝無疑。

假設 n = 2。若用 (x,y) 表示某一輪中兩堆石子的數目(總假定 x <= y),則 (x,y) 也可以看成遊戲中的一個狀態。最終態為 (0,0)。這時,輪到的選手落敗。當輪到小明時,若此時的狀態為 (0, x) 且 x>0,則問題化為 n=1的情況,從而小明必勝。進一步考慮複雜些的狀態,例如 (1, x), x>= 1。當 x=1 時,小明必輸。其實當狀態為 (x,x) 型時(兩堆石子數目相同),小明都必敗,因為,無論小明如何取走和移動石子,小紅都可以通過取走合適數目的石子,把狀態重新調整為 (y,y)型。同時也容易看出,若為其它型別的狀態,則小明必勝。

再考慮 n = 3。如果小明可以通過取走和移動石子把狀態調整成 (0,x,x) 型,則小明可以獲得最終的勝利。事實上,小明確實可以做到。證明如下:假設當前狀態為 (x,y,z),並不失一般性,假設 x<=y<=z。則 y-x < y <= z。通過在 z 堆中取走 z-(y-x) >= 1 個石子,並把 y-x 個石子移動到 x 堆上,可以把狀態 (x,y,z) 轉換成 (0,y,y)。

看來,兩堆石子數目相同是個很特殊的狀態。然而,現在尚不清楚,對於更多的堆,情況是如何的。於是,接著考慮 n = 4。顯然,(1,1,1,1) 是必敗狀態,(1,1,2,2) 也是如此。可以猜測當小明面對 (x,x,y,y) 型狀態時必敗。要證明這是必敗狀態,則需要證明,無論採用什麼策略,小明結束該輪之後,狀態不是 (x,x,y,y) 型,並且,小紅可以在接下來的一輪中,把狀態重新調整成 (x,x,y,y) 型。這樣,小明最終會被逼面臨 (0,0,0,0) 這個終態,從而輸掉遊戲。簡單的思考可以驗證" (x,x,y,y)型狀態是小明的必敗狀態" 這一結論。

現在,要把上述的結論推廣到任意數目的堆。當 n 為偶數時,我們把狀態  (x1,x1,x2,x2,...,xm,xm),即,當有偶數堆,並且可以把這 n 堆分成 n/2 組,每組由兩個石子數目相同的堆組成的狀態, 稱為目標狀態。現在我們證明,目標狀態是小明的必敗狀態;而其它狀態是他的必勝狀態。

引理一:當 n 為偶數,且選手面臨目標狀態,則無論選手採取何種策略,在結束該輪之後的狀態一定不是目標狀態。

證明:用反證法。假設命題不成立。則結束該輪之後的狀態可以寫為 (y1,y1,y2,y2,...,ym,ym),不失一般性,假設 y1<=y2<=...<=ym 和 x1<=x2<=...<=xm。 考慮分組 {xk,xk}中的兩個堆。其中至少有一個堆不是被選手選中的堆。顯然,這個堆對應  (y1,y1,y2,y2,...,ym,ym) 中的某個分組 {yt,yt}中的某個堆。同時,因為這個堆沒被選中,其石子的數目不會減少,因此,yt>=xk。由於(x1,x1,x2,x2,...,xm,xm) 和  (y1,y1,y2,y2,...,ym,ym) 中的堆存在一一對應的關係,從而對每個 xk,惟一對應著一個yt,並且 有xk<=yt 。這說明,2(x1+x2+...+xm) <= 2(y1+y2+...+ym),即結束該輪後,總的石子數目不減。但這是不可能的。證畢。

注:在上述證明中,可以證明更強的結論:對所有 k, 成立xk <= yk

引理二:當選手面臨的狀態不是目標狀態時,總是可以採取某個策略,使得該輪結束後,狀態為目標狀態。

證明:不妨假設面臨的狀態為 (x1,x2,...,xn),x1 < x2 <  ... < xn(若有兩個數目相同的堆,則無須對它們進行任何操作,因此,可以把任何兩個數目相同的堆排除在考慮之外)。當 n=2m 偶數時,選擇堆 xn,並進行如下操作:把x2k+1-x2k 個石子移到堆x2k,1<=k<= m-1。這樣,總共需要從堆 xn 中移出 M=(x3-x2)+(x5-x4)+...+(x2m-1-x2m-2)<xn-x1。接著,取走 xn-M-x1>0 個石子。當 n = 2m+1 為奇數時,同樣選擇堆 xn,並進行如下操作:把 x2k-x2k-1 個石子移動到堆 x2k-1,1<=k<=m。這樣,總共需要從堆 xn 中移出 M=(x2-x1)+(x4-x3)+...+(x2m-x2m-1)<xn-x1 接著,取走剩下的所有 xn-M>0 顆石子。

定理:當 n 為偶數且初始狀態為目標狀態時,小明必敗;否則,必勝。

至此,問題完美解決。程式碼很簡單,只需要檢測 n 的奇偶性。當 n 為偶數時,進一步檢測每堆的石子數目出現的次數是否為偶數。若採用雜湊表,則當 n 為偶數時,時間複雜度為 O(n);為奇數時,O(1)。

PS:很久沒做 POJ 了。最近在研究博弈論,於是順便把 POJ 中有關博弈的題目做一做......

相關推薦

ACM PKU POJ 1740 解題報告 -- 男人

題意:小明和小紅參加一種新的取石子游戲。遊戲開始時有 n 堆石子,參與遊戲的兩個選手輪流取走和移動石子,遊戲從小明開始。在每一輪中,選手選擇一個至少有一顆石子的堆,從該堆石子中拿走至少一個石子。接著,該選手可以多次地從該堆中剩下的石子中把任意多的個石子移動到任意的堆中。當然

ACM PKU POJ 1112 解題報告

問題描述:給定 n (1 < n < 101) 個人,以及資訊某個人 i 是否認識 j (1<=i<=n, 1<=j<=n, i != j),你的任務是把這 n 個人分成大小近可能相近的兩隊,使得 1)每個人屬於且只屬於某一隊;2)每個隊的

poj 樓天成的男人系列 A New Stone Game 博弈問題

第一,只有一堆x,第一個人直接全部取走就勝利了.(顯然x,y,y的情況也是第一人勝,所以忽略相等的石頭); 第二,x,y的形式(這裡不妨假設遞增,下同).第一人從第二堆中取走(y-x)個石頭,這樣兩

有向圖的匯點 -- 兼 ACM PKU POJ 2186 ( Popular Cows ) 解題報告

題意:奶牛的夢想是成為牛群中最受歡迎的奶牛,即受其它所有牛的歡迎。“歡迎”是具有傳遞性,即如果牛A認為牛B受歡迎,牛B覺得牛C受歡迎,則牛A也隱含地認為牛C受歡迎。現在,給一組點對 (A,B) 表示 A 認為 B 受歡迎,找出有多少最受歡迎的奶牛。 這是一個有向圖上的問題

POJ 1741 男人——樹分治

tor pst def roo 容易 air sizeof ram 出發 Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 23829 Accepted

2016-2017 ACM-ICPC CHINA-Final 解題報告

題目連結 A. Number Theory Problem 題意:給你一個數N,求形如2k-1且小於2N的數中有多少能被7整除。 解法:觀察二進位制位找規律,答案是N/3。 #include<bits/stdc++.h> using namespace std; ty

杭電acm公選課作業解題報告——第三章 貪心演算法。

課堂筆記: 在對問題求解時,總是作出在當前看來是最好的選擇。也就是說,不從整體上加以考慮,它所作出的僅僅是在某種意義上的區域性最優解(是否是全域性最優,需要證明)。很多貪心型別的題目都不是最樸素的貪心,而是需要做一些變化,對於我們,關鍵是找到貪心的本質! 求解基本步驟:

POJ 1401 解題報告

這道題是求N!的結果後面連續的0有多少個,實際上10 = 2 x 5,而2的個數又大於5,所以相當於求N!的5的質因數個數有多少個。n/5 + n/25 + n/125 + ...即可。 我確信小學奧數的時候學過。每感於小學奧數學過這麼多,後面這麼多年幹啥去了。 注意fiv

杭電ACM hdu 2152 Fruit 解題報告(母函式)

Problem Description 轉眼到了收穫的季節,由於有TT的專業指導,Lele獲得了大豐收。特別是水果,Lele一共種了N種水果,有蘋果,梨子,香蕉,西瓜……不但味道好吃,樣子更是好看。 於是,很多人們慕名而來,找Lele買水果。 甚至連大名鼎鼎的HDU ACM

POJ 1154 解題報告

這道題是普通的DFS,不需要優化就可以通過。 1154 Accepted 164K 32MS C++ 1326B /* ID: thestor1 LANG: C++ TASK: poj1154 */ #include <iostream> #inclu

POJ 1661 解題報告

這道題可以看做是DP也可以看成模擬。從上往下看每個平臺能否到達,是否遮擋,是否到地。程式碼寫得重複很多,應該可以簡潔許多。 需要注意的地方是這裡把出發點也看做了一個平臺,這樣按照平臺高度排序的時候需要排N+1個(而不是N個)。 1661 Accepted 180K 0MS

poj 1014 解題報告

題目描述:, 一群珠子,分別有價值為1,2,3,4,5,6,每個珠子的個數進行輸入為n1 n2 n3 n4 n5 n6,判斷能否分成兩堆價值相等的珠子。 解法分析: 本題我採用的是多重揹包策略。當價值m%2=1時,不可分,否者揹包容量為m/2時的最大容量,最後判斷w[m]=

POJ 1363 解題報告

這道題不難但是題目很難理解。看了測試樣例才明白,如果入棧順序是遞增的:1,2,3,4,5. 那麼給出一個出棧順序,比如5,4,1,2,3,判斷這個出棧順序是否可能。 我這裡就是按照題意模擬的。比如碰到5,就將小於等於5的都入棧(1,2,3,4,5),然是將5出棧(判斷這時棧

A Bug‘s life POJ 2492 解題報告 (種類並查集)

   這也算是種類並查集的一道經典例題了吧,題意就不多解釋了,先寫一些我對種類並查集的一些理解。    種類並查集比普通的並查集多一個relation陣列,relation[i] 記錄了 i 和 其直接父親節點的關係,這個關係的表示因題目而異,種類並查集的重點和難點就是

POJ 2243解題報告

BFS #include <stdio.h> #include <memory.h> #include <stdlib.h> const int maxn=15; int visit[maxn*maxn]; int dir[8][2]={

POJ 1308 解題報告

這道題我用的是並查集(union-find)確定沒有環,再看看邊數是不是節點數減一(確定是否聯通)做的。 AC後看了discuss,發現並不能通過2 1 3 1 0 0 這種資料(但是OJ上沒有這樣的資料)。看來還是需要檢查每個節點的入度,保證一個節點入度為0,其餘節點入度

[ACM] hdoj1018 Big Number 解題報告

題目傳送門 題目大意 給出一個整數n,n的範圍為1 < n < 10^7,計算n!的位數。 解題思路 計算n!的位數,及計算n!最高位是10的幾次冪,即計算log10(n!),根據

POJ 3278 解題報告

這道題是個BFS的問題,因為要求的是一個相鄰節點間距離都為1的graph中兩個節點間的最短距離。一開始上來用的DFS,結果可想而知。 3278 Accepted 844K 63MS G++ 1192B /* ID: thestor1 LANG: C++ TASK:

poj 2376解題報告(詳細) 帶幾組測試資料

farmer John要安排他的牛清理牛棚,一共有T個牛棚要清理,每頭牛可以清理相鄰的牛棚。比如,一頭牛可以清理4-7號牛棚。當然了,牛清理的牛棚可以重疊。現在要你求出可以完成牛棚的清理的最少頭牛的個數,不可以就輸出-1. 一道區間重疊問題。排序+貪心可解

leetCode解題報告5道(十)

ddl peek path sum ron 表示 bar largest ger 不能 題目一:Valid Number Validate if a given string is numeric. Some examples: "0&quo