約瑟夫環問題的通俗解釋

2021-10-14 04:18:37 字數 2714 閱讀 3917

約瑟夫環問題

這個問題是以弗拉维奧·約瑟夫命名的,他是1世紀的一名猶太歷史學家。他在自己的日記中寫道,他和他的40個戰友被羅馬軍隊包圍在洞中。他們討論是自殺還是被俘,最終決定自殺,並以抽籤的方式決定誰殺掉誰。約瑟夫斯和另外乙個人是最後兩個留下的人。約瑟夫斯說服了那個人,他們將向羅馬軍隊投降,不再自殺。約瑟夫斯把他的存活歸因於運氣或天意,他不知道是哪乙個。

—— 【約瑟夫問題】維基百科

我們細化一下規則:

在一間房間總共有n個人(下標1~n),只能有最後乙個人活命。按照如下規則去排除人:

所有人圍成一圈

順時針報數,每次報到q的人將被排除掉

被排除掉的人將從房間內被移走

然後從被kill掉的下乙個人重新報數,繼續報q,再清除,直到剩餘一人

你要做的是:當你在這一群人之間時,你必須選擇乙個位置以使得你變成那剩餘的最後一人,也就是活下來。

解決思路

解決約瑟夫環問題,最重要的是要發現乙個很重要的規律。

假設有10個元素站成一對進行這個遊戲,隊頭和隊尾看成是連在一起的,編號為a b c d e f g h i j。從a開始報數,每次報到3的元素被刪除。

一開始,a b c d e f g h i j

第1輪:c被移走,a b d e f g h i j

第2輪:f被移走,a b d e g h i j

第3輪:i被移走, a b d e g h j

第4輪:b被移走, a d e g h j

第5輪:g被移走,a d e h j

第6輪:a被移走, d e h j

第7輪:h被移走, d e j

第8輪:e被移走, d j

第9輪:j被移走, d

上述遊戲過程找規律不明顯,我們額外增加乙個操作:每次選中的元素被刪除後,剩下的所有元素都進行迴圈左移操作,然後下輪遊戲依然從佇列頭部開始。比如第一輪過後,c 被刪除,佇列變成:a b d e f g h i j,這時將 d e f g h i j 移動到隊頭,把 a b 移動到隊尾,新列隊變成 d e f g h i j a b,第二輪遊戲從元素d開始進行。不難發現,雖然每輪遊戲過後,每個元素的位置發生了變化,但是它們的相對次序並沒有改變,所以額外增加的移動操作不會影響到最終結果。現在,重新進行上述過程。

一開始,a b c d e f g h i j

第1輪:c被移走,d e f g h i j a b

第2輪:f被移走,g h i j a b d e

第3輪:i被移走, j a b d e g h

第4輪:b被移走, d e g h j a

第5輪:g被移走,h j a d e

第6輪:a被移走, d e h j

第7輪:h被移走, j d e

第8輪:e被移走, j d

第9輪:j被移走, d

每一輪遊戲前後,每個元素其實都向前迴圈移動了3個位置,這個過程可以用下列等式描述:

p(n) = p(n+1) - 3 + k * len(n+1) ,(k = 0, 1, 2, …)

p(n+1) 和 p(n) 分別表示一輪遊戲前後某元素在佇列中的位置, len(n+1) 表示該輪遊戲前佇列的總長度, k 是整數,保證p(n+1) - 3 + k * len(n+1) >= 0, 等於0的元素就是該輪遊戲將要刪除的元素。舉個例子,觀察元素e,在第一輪遊戲之前,它的位置是5, 佇列長度 len(n+1) = 10,第一輪遊戲之後,位置變成了2;觀察元素a,在第四輪遊戲之前, 它的位置是2,佇列長度是 len(n+1) = 7,第四輪遊戲之後,位置變成了6。

顯然,在遊戲結束後,最終留下來的人位置是1,對上述等式進行移位運算得到:

p(n+1) = p(n) + 3 - k * len(n+1) ,(k = 0, 1, 2, …)

這個等式可以用模運算來表示:

p(n+1) = ( p(n) + 3 ) % len(n+1),

這裡有一點需要特別注意:由於模運算結果會出現0,而在上述公式中,位置資訊都是從1開始的,運算結果p(n+1) = 0其實表示的是佇列的最後乙個元素。

有了這個關係式,**就很好寫了:

public class ringsolution 

/*** 下標從 1 開始

* @param n 表示一共有 n 個元素參加遊戲

* @param target 表示報數到 target 的人被帶走

*/private static void ring(int n, int target)

}/**

* 下標從 0 開始

* @param n 表示一共有 n 個元素參加遊戲

* @param target 表示報數到 target 的人被帶走

*/private static void ringzero(int n, int target) }}

如果下標是從0開始,就不需要額外處理模運算結果p(n+1) = 0情況,**可以進一步簡化,如上所示,程式執行結果:

約瑟夫問題 約瑟夫環

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

約瑟夫問題 約瑟夫環

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

約瑟夫環公式法解釋

公式法 f n,m f n 1,m m n f 1,m 0 索引從0開始 f是每一輪中存活的人對應的編號。遞推過程如下 設編號為2的出局 即m 3 已知f 1,m 0,即只有乙個人的隊伍中,存活的肯定是編號0 從最後一輪f 1,m 求解倒數第二輪f 2,m 倒數第二輪有兩個人,殺掉乙個人後剩餘一人 ...