历史:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
题目:
约瑟夫环问题。13个人围成一圈,从第一个开始报数,报到 “3”退出圈子,按顺序输出退出圈子的序号。
代码:
#include<stdio.h>
#include<math.h>
#define N 30
void Josephus();
void Josephus(int a[],int n,int s,int m)
/*约瑟夫问题,将出圈的人的序号依次存放在数组中*/
{
int i,j,s1,t;
s1=s; /*开始报数的序号*/
for(i=1;i<=n;i++) /*初始化*/
a[i-1]=i;
for(i=n;i>=2;i--) /*i为当前圈中的人数*/
{
s1=(s1+m-1)%i; /*s1为将要出圈的序号*/
if(s1==0) /*如果s1=0说明,将要出圈的人的序号为s1*/
s1=i;
/*将序号s1的人出圈,即将序号为s1数移到到数组的末尾*/
t=a[s1-1];
for(j=s1;j<=i-1;j++)/*将s1后的数依次前移*/
a[j-1]=a[j];
a[i-1]=t;/*将序号为s1的数存储在a的末尾*/
}
}
void main()
{
int i,a[N];
int n=13,m=3,s=1;
Josephus(a,n,s,m);
printf("出圈的依次编号为:");
for(i=n-1;i>=0;i--)
printf("%-4d",a[i]);
printf("\n");
}
输出:
出圈的依次编号为:3 6 9 12 2 7 11 4 10 5 1 8 13