題意:有兩堆石子,兩人輪流取石子,輪到某人時,有兩種取法,要麼從兩堆石子中同時取出一定數量的石子,要麼只從一堆中取任意數量的石子,不能不取。不能取的人判為輸。
普通思想:對於博弈問題,首先想到的就是sg函式。所以我們先從小到大的看局面。可以得出,對於每一種狀態(x,y)x,y為石子堆。要麼(x,y)本身是必敗態,要麼(x,y)就是必勝態,因為每種必勝態的(x,y)局面都可以通過同時從兩堆取相同數量的石子或者從某一堆去一定數量的石子,使得對手面對的是必敗態。下面介紹如何得出的:
(0,0)為必敗態,(1,2)為必敗態,這個是顯然的,很顯然了。不是那些大神的部落格裡的那些顯然,那些顯然一點都不顯然。。。
然後可以推出:(3,5)為必敗態,而(2,1)這種相反的就不用說了。對於某種必敗態來說,其x,y值是確定的,若只改變其中乙個值,則局面必然是必勝態。因為只要拿走多餘的,則必然可以使得對手面對必敗態。因此,我們只要從x=0開始一直往後面推算,只要x的值在之前的x和y中沒有出現過,那麼必然有乙個y>x,使得(x,y)是必敗態,而這個差值,根據推算,可以得出是逐一遞增的,也就是每相鄰的兩個必敗態的y-x的值只相差1.如:
0:(0,0)
1:(1,2)
2:(3,5)
3:(4,7)
4:(6,10)
根據上面的推式,我們可以用乙個for迴圈得到所有的必敗態。將其存放到乙個陣列裡。然後我們再用乙個一維陣列儲存y-x的差值得必敗態的x的值,陣列下標即為y-x。
根據上面兩個陣列,我們就可以計算出每乙個局面先手的勝負,然後在輸出的時候,我們要考慮的就是如果當前局面是必敗態,則輸出0,如果不是,則先看同時取,
對於同時取:根據y-x的差值,得到離其最近的必敗態的x值,用當前x減去之就是同時取的石子數(若x小於它,則不能同時取),輸出並記錄,避免重複輸出。
對於一堆取:根據x值所對應的必敗態的y,與當前的y對比,若當前的大,則直接輸出x的必敗態,如比當前小,則判斷y的必敗態的y,與當前的x比,若比當前的小,則輸出y的必敗態。若小,不可能出現這種情況。(證明很簡單,根據bk = ak + k,可以得證)
到此所有情況都考慮到了,1a。(其實此題就是威佐夫博奕,下面會講)
普通思想**:
#include #include #include #include using namespace std;
const int max__ = 1000010;
int vis[max__],dis[max__];
void init()
}}int main()
printf("1\n");
if(a == b)
continue;
}if(a == 0 || b == 0)
if((b-a == vis[dis[b-a]] - dis[b-a])
||(b-a == dis[b-a] - vis[dis[b-a]]))
}if(vis[a] < b)
if(vis[b] < a)
}return 0;
}
威佐夫博奕:有兩堆各若干個物品,兩個人輪流從某一堆或同
時從兩堆中取同樣多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。
這種情況下是頗為複雜的。我們用(ak,bk)(ak ≤ bk ,k=0,1,2,…,n)表示
兩堆物品的數量並稱其為
局勢,如果甲面對(0,0),那麼甲已經輸了,這種局勢我們 稱為
奇異局勢
。前幾個奇異局勢是:
(0,0)、
(1,2)、 (
3,5)、
(4,7)、
(6,10)、
(8,13)、
(9,15)、
(11,18)、
(12,20)。
那麼任給乙個局勢(a,b),怎樣判斷它是不是奇異局勢呢?我們有如下公式:
ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括號表示取整函式)
同樣對應兩種取法:
同取:利用公式:abs(
temp-a)==
abs(
temp+k-b)且temp < a 則可以同時取,輸出之
一堆取:對於局面(a,b),將1至b的所有奇異局勢與a,b對比,若有乙個值是相等的,則即為答案,輸出之。
威佐夫博奕**:
#include #include #include #include using namespace std;
int main()
//一堆中取
if(a==0) //0 0情況,第一種奇異局勢
printf("0 0\n");
for(i=1;i<=b;i++)}}
return 0;
}
hdu 2177 取 2堆 石子遊戲
威佐夫博弈變異,要求輸出能贏的售後第一次能取得情況。3.一定存在規則允許的某種操作可將必勝點移動到必敗點 證明 以某個必勝點 i,j 為例。因為所有自然數都會出現在某個必敗點中,故要麼i等於m k 要麼j等於n k 若i m k j n k 可從j中取走j n k 個石子到達必敗點 若i m k j...
hdu 2177 取 2堆 石子遊戲
天資愚笨啊,網上的一大堆沒看懂。總結百科的方法為 1.a b 同時減去a 得到0,0 2.a a k b b k b b b k 3.a a k b同時拿走a k a b a k 得到 a b a k a b a k b a k 4.a a k b b k 從a中拿走 a a k 5.a5.1 a ...
HDU 2177 取 2堆 石子遊戲
有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子 二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。如果...