約瑟夫問題

2021-08-22 16:25:59 字數 2416 閱讀 9296

n個人(編號0~(n-1)),從0開始報數,報到(k-1)的退出,剩下的人繼續從0開始報數。求勝利者的編號。

1.迴圈鍊錶模擬

#include 

using

namespace

std;

struct node;

int main()

else

if( n==1)

else

temp->next = start;//將尾部指標指向頭部

node* p = start;

int realk = k;

while( n>1 )

else

predele = p;

todele = predele->next;

cout

<

next;

delete todele;

--n;

//p指向下乙個,開始另外一輪

p = p->next;

}cout

<

}return

0;}

2.遞迴
#include 

using namespace std;

/*我們知道第乙個人(編號一定是( m mod n) 出列之後,剩下的n-1個人組成了乙個新的約瑟夫環(以編號為k=(m mod n)+1的人開始):

k+1 k+2

... n-2,n-1,0,1,2,... k-2,k-1

並且從k開始報0。

現在我們把他們的編號做一下轉換:

k+1 --> 0

k+2 --> 1

......

k-1 --> n-2

變換後就完完全全成為了(n-1)個人報數的子問題,假如我們知道這個子問題的解:例如x是最終的勝利者,那麼根據上面這個表把這個x變回去不剛好就是n個人情況的解嗎?!!變回去的公式很簡單,相信大家都可以推出來:x2 = [x+(k+1)] mod n

如何知道(n-1)個人報數的問題的解?對,只要知道(n-2)個人的解就行了。(n-2)個人的解呢?當然是先求(n-3)的情況 ---- 這顯然就是乙個倒推問題!好了,思路出來了,下面寫遞推公式:

令f表示i個人玩遊戲報m退出最後勝利者的編號,最後的結果自然是f[n]

遞推公式

f[1]=0;

f=[ f[i-1]+(k+1) ] mod i; (i>1)

每傳遞k次,就淘汰拿著土豆的那個人

*/int main()

cout<1

int f( int num ,int k )

3.遞迴2
在每一輪報數過程中,都有n/k個人退出了隊伍,比如n = 10, k = 3,第一輪有n / k = 3三個人退出;

上述第一種方法每次遞迴的步長為1,這裡我們利用上述關係,建立乙個步長為n / k的遞迴過程;

需要注意的是,當n減少到n = k的時候就需要使用第一種遞迴進行計算;

n > k時的遞迴公式為:

ret < n mod k: ret = ret - (n mod k) + n

ret >= n mod k: ret = ret - (n mod k) + (ret - n mod k) / (k - 1)

解釋一下(比較醜哈哈):

比如,就上面這個圖,在淘汰掉2,5後,還剩5個人。從6號開始重新從0開始編號。那麼這時候勝利者就有兩種情況:

一:勝利者的新編號小於n%k,對這個圖而言,也就是處於0或1的位置,這時推算它在原來序列中的編號 = 新編號 - n%k + n; 比如0是勝利者,那麼它原來序列中的編號就為:0-7%3+7 = 6。

二:勝利者的新編號不小於n%k,對這個圖,也就是處於2,3,4,5(新編號)的位置,這時我們再來推算它在原序列中的編號,先減去末尾的(n%k),免受其影響,這樣,2,3,4,5就變成0,1,2,3。還要考慮被淘汰的元素對新編號的影響(比如原序列中2號的淘汰對新編號中4,5號產生影響),應該減去。也就是 - (新編號- n mod k) / (k - 1)。

#include 

using

namespace

std;

int josephus(int n, int k)

//執行遞迴過程

ret = josephus(n-n/k,k);

if(ret < n % k)

else

return ret;

}int main()

return

0;}

參考:

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...

約瑟夫問題 約瑟夫環

約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...

約瑟夫問題

這是17世紀的法國數學家加斯帕在 數目的遊戲問題 中講的乙個故事 15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了乙個辦法 30個人圍成一圓圈,從第乙個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次...