问题提出:试编写一个求解Josephus问题的函数。用整数序列1,2,3,...,n表示顺序围坐在圆桌周围的人,并采用数组表示作为求解过程中使用的数据结构。然后使用n=9,s=1,m=5,以及n=9,s=1,m=0,或者n=9,s=1,m=10作为输入数据,检查你的程序的正确性和健壮性。
我的思路:
1.n个人围城一圈,则创建一个数组来表示这些人,并且给他们编号。从a[0]到a[n-1]
2.若是从第s个人开始报数,则这个人的数组下标应该是s-1。
3.采用一个N-1次的循环来逐个剔除圆圈中的人,并且把剔除的人逐个排在数组里(从a[n-1]一直到a[1])
4.采用i=(i+m-1)%k这个方法来定位我们要找剔除的人所在的下标位置。
程序:
#include "stdafx.h"
#include<stdlib.h>
#using <mscorlib.dll>
#include <iostream>
using namespace std;
void Josephus(int a[],int n,int s,int m);
int _tmain()
{ int i, n,m,s;
cout<<"假设有n个人坐在圆桌的周围:"<<endl;
cout<<"从第s个人开始数起,到第m个人的时候,出局"<<endl;
cout<<"请输入n,s,m的值:"<<"";
cin>>n>>s>>m;
cout<<endl;
int *a; //定义一个动态数组
a=new int[n];
if(a[n] ==NULL)
{
cerr<<"内存分配错误!"<<endl;
}
if(m==0){
cerr<<"m=0是无效的参数!"<<endl;
cout<<"再次输入m的值:"<<endl;
cin>>m;
}
Josephus(a,n,s,m);
cout<<endl;
cout<<"n个人出局的顺序:"<<endl;
for(i=0;i<n;i++) cout<<a[i]<<'/t';
cout<<endl;
delete[] a;
return 0;
}
void Josephus(int a[],int n,int s,int m)//n个人围坐在一个圆桌周围,从第s个人开始报数,数到第m个人,让他出局
{
int i,j,k,tmp;
for(i=0;i<n;i++) a[i]=i+1; //初始化,执行n次
i=s-1; //报名起始位置
for(k=n;k>=1;k--){ //逐个出局,执行n-1次
if(i==k) i=0;
i=(i+m-1)%k; //寻找出局的位置
if(i!=k-1){
tmp=a[i]; //出局者交换到第k-1位置
for(j=i;j<k-1;j++) a[j]=a[j+1];//挪位,从出局者后面那个为出局者开始改变下标,每个下标减1.
a[k-1]=tmp;
}
}
for(k=0;k<n/2;k++){ //全部逆置,得到出局序列
tmp=a[k];
a[k]=a[n-k-1];
a[n-k-1]=tmp;
}
}