約瑟夫環問題
這個問題是以弗拉维奧·約瑟夫命名的,他是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上述遊戲過程找規律不明顯,我們額外增加乙個操作:每次選中的元素被刪除後,剩下的所有元素都進行迴圈左移操作,然後下輪遊戲依然從佇列頭部開始。比如第一輪過後,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開始進行。不難發現,雖然每輪遊戲過後,每個元素的位置發生了變化,但是它們的相對次序並沒有改變,所以額外增加的移動操作不會影響到最終結果。現在,重新進行上述過程。第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
一開始,a b c d e f g h i j每一輪遊戲前後,每個元素其實都向前迴圈移動了3個位置,這個過程可以用下列等式描述:第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
p(n) = p(n+1) - 3 + k * len(n+1) ,(k = 0, 1, 2, …)顯然,在遊戲結束後,最終留下來的人位置是1,對上述等式進行移位運算得到: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。
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 倒數第二輪有兩個人,殺掉乙個人後剩餘一人 ...