做約瑟夫的時候被難住了一次,第一次寫部落格就拿約瑟夫開刀吧(壞笑),並且在網上找到的約瑟夫題解有些迷茫(我是演算法小zz),所以發表一下我的見解
首先認識一下什麼是約瑟夫問題:
n 個人的編號是 1~n,如果他們依編號按順時針排成乙個圓圈,從編號是1的人開始順時針報數。
(報數是從1報起)當報到 k 的時候,這個人就退出遊戲圈。下乙個人重新從1開始報數。
求最後剩下的人的編號。這就是著名的約瑟夫環問題。
本題目就是已知 n,k 的情況下,求最後剩下的人的編號。
題目的輸入是一行,2個空格分開的整數n, k
要求輸出乙個整數,表示最後剩下的人的編號。
對於這種問題,我們可以把這這個模擬成乙個圓桌,每次刪除固定的元素然後一直到只剩下乙個元素為止,在輸出這個元素
我們可以採取stl函式庫中的vector,用動態陣列解決這個問題,**如下
但是很遺憾,兩個平台都給的是tle,這是為什麼呢?
其實很容易相同,在乙個迴圈中頻繁的刪除元素,就要把這個元素的後面所有元素向後移或者前移動,多次移動就會導致效率很低,所以不得不思考別的解法;
分析一下:
對於任意的n,k;
我們可以設定f(q)為每次踢出第q個人最後的結果
0 1 2 3 4 5 6 .... n-1;
q q+1 q+2...........q-2(我們要kick off的是q+1這位兄台);
再次重複一下,將新的被殺的後乙個人作為新的0號,於是新的如下:
0 1 2 3 4 5 .......n-2;
遞推一下:
然後在想,
先是n個人玩這個遊戲,編號從0->n-1,數m退出,當第乙個m-1號人退出後,就變成了n-1個人玩這個遊戲了,將這n-1個人重新編號,如圖,會發現是由(原來的編號 - m)得到這重新編的號。那麼這時問題變成了n-1個人玩這個遊戲了,設f(n)表示n個人數m退出時問題的解,那麼f(n-1)是n-1個人數m退出時問題的解,假設f(n-1)已求出,那麼:
f( n ) = f(n - 1) + m;
並且是迴圈刪除,所以
f( n ) = (f(n - 1) + m)%n;
那麼,當得知f(n-2)的解時,反推至f(n-1)時,需要編號不超過n-1,因此等式為:
f(n-1)=(f(n-2) + m) % n-1;
那麼推廣到一般:f( n ) = (f (in- 1) + m )% n;
到最後剩下乙個人的時候直接輸出下標0就可以啦;
附上**
#includeusingnamespace
std;
int yuesefu(int n,int
m)int
main()
約瑟夫問題 約瑟夫環
約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...
約瑟夫問題 約瑟夫環
約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...
約瑟夫環問題
約瑟夫環問題 問題描述 編號是1,2,n的n個人按照順時針方向圍坐一圈,每個人持有乙個密碼 正整數 一開始任選乙個正整數作為報數上限值m,從第乙個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向的下乙個人開始重新從1報數,如此下去,直到所有人...