約瑟夫環問題求解--程式+詳細註解
阿新 • • 發佈:2019-01-01
約瑟夫環問題起源於一個猶太故事。約瑟夫環問題的大意如下
羅馬人攻佔了橋塔帕特,41個人藏在一個山洞中躲過了這場浩劫。這41個人中,包括歷史學家約瑟夫和他的一個朋友。剩餘的39個人為了表示不向羅馬人屈服,決定集體自殺。大家決定了一個自殺方案,所有這41個人圍成一個圓圈,由第1個人開始順時針報數,每報數為3的人就立刻自殺,然後再由下一個人繼續報數,仍然是每報數為3的人就立刻自殺……,直到所有人都自殺身亡為止。
約瑟夫和他的朋友並不想自殺,於是約瑟夫想到了一個計策,他們兩個同樣參與到自殺方案中,但是最後卻躲過了自殺。請問,他們是怎麼做到的?
下面是約瑟夫環示意圖
package 約瑟夫環問題; import java.util.*; public class Example { static final int Num=41;//參與者的人數總和 static final int Kill=3;//死亡數字,每數到3便自殺 static void Josephus(int alive){ int[] man=new int[Num]; int count=1; int i=0,pos=-1; while(count<=Num){ do{ pos=(pos+1)%Num; //構建約瑟夫環,不斷除以Num取餘數,則pos永遠是0-Num之間迴圈 /* * man[]只是一個大小為Num的陣列,但是內容為空 * 在沒進行賦值之前,所有的man[i]==0 * 這條語句的作用是不停的找到陣列中沒有賦值的元素位置,也就是還沒有自殺的人 */ if(man[pos]==0){ i++; } //如果i迴圈到死亡數字Kill,則i清零以便下次迴圈,同時退出當前while迴圈 if(i==Kill){ i=0; break; } }while(true); //為死亡者標上死亡次序count,count是從1到41的 man[pos]=count; System.out.printf("第%2d個人自殺!是第%2d個自殺的",pos+1,man[pos]); System.out.print(" "); if(count%2!=1) System.out.println(); count++; } System.out.println("\n"); System.out.printf("這%d個想要存活下來的初始位置應排在以下序號:\n",alive); alive=Num-alive;//最後一個不想活的自殺次序 /* * 遍歷所有人,想要活下幾個就找到死亡次序中最後幾個對應的排列序號 * 也就是對應的陣列下標+1 */ for(i=0;i<Num;i++){ if(man[i]>alive){ System.out.printf("初始編號:%d,約瑟夫編號:%d\n",i+1,man[i]); } } System.out.println(); } public static void main(String[] args) { int alive; //輸入想活下來的人數alive Scanner input=new Scanner(System.in); System.out.println("輸入想要存活下來的人數:"); alive=input.nextInt(); Josephus(alive); } }
機智的約瑟夫和他的朋友選擇了16號和31號,最終39人先於他們而去,他們成功擺脫了撒旦的糾纏