1. 程式人生 > >約瑟夫環問題求解--程式+詳細註解

約瑟夫環問題求解--程式+詳細註解

約瑟夫環問題起源於一個猶太故事。約瑟夫環問題的大意如下

羅馬人攻佔了橋塔帕特,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人先於他們而去,他們成功擺脫了撒旦的糾纏