這是17世紀的法國數學家加斯帕在《數目的遊戲問題》中講的壹個故事:15個教徒和15 個非教徒在深海上遇險,必須將壹半的人投入海中,其余的人才能幸免於難,於是想了壹個辦法:30個人圍成壹圓圈,從第壹個人開始依次報數,每數到第九個人就將他扔入大海,如此循環進行直到僅余15個人為止。問怎樣排法,才能使每次投入大海的都是非教徒。
*問題分析與算法設計
約瑟夫問題並不難,但求解的方法很多;題目的變化形式也很多。這裏給出壹種實現方法。
題目中30個人圍成壹圈,因而啟發我們用壹個循環的鏈來表示。可以使用結構數組來構成壹個循環鏈。結構中有兩個成員,其壹為指向下壹個人的指針,以構成環形的鏈;其二為該人是否被扔下海的標記,為1表示還在船上。從第壹個人開始對還未扔下海的人進行計數,每數到9時,將結構中的標記改為0,表示該人已被扔下海了。這樣循環計數直到有15個人被扔下海為止。這個是願意。
現在的衍生問題
就是說有n個人圍成壹圈,然後說從任意指定的壹個
人那裏為起點,以m個人為單位,每轉m個人第m個人被殺死。當起始人也就是所謂的
第1個人是最後被殺死的,這個m就是為所求,滿足這樣就叫joseph問題。
然後帶壹個超叼的遞歸實現
#include<iostream.h>
#include<stdlib.h>
void make(int *base,int n,int pos,int c,int m)//參數的意義。base數組名,n數組長度。pos跑格的壹個東西。c計算次數的。m每次跑路的長度。
{
int j=0;
cout<<"NO. "<<++c<<" 第"<<pos+1<<"位出列"<<endl;//輸出
base[pos]=0;//踢掉
if(c==n)return; //出口
while(j-m)if(base[pos=(pos+1)%n])j++;//遞歸點 ,每次數到幾這個3就改到幾
make(base,n,pos,c,m);//遞歸
}
int main()
{
int n,m,c=0,pos;//從N開始數,則把pos改為N-1就行了.
cout<<"請輸入總人數"<<endl;
cin>>n;
cout<<"請輸入要隔幾個人:"<<endl;
cin>>m;
int *base=new int[n];
for(int i=0;i<n;i++)base[i]=1;
pos=m-1;
make(base,n,pos,c,m);
delete[]base;
system("PAUSE");
return 0;
}