据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏
/*
* 内容:约瑟夫问题(Josephus Problem)
* 时间:2/11/2013
*/
#include <stdio.h>
#define NUMBER 41
#define DEATH 3
//第一种方法,记录每个人的死亡顺序
void firstFunction(int josephus[])
{
int count = 1;//记录自杀人的顺序
int flag = 0;//标记报数的人数
int pos = -1;
while (count <= NUMBER)
{
do
{
pos = (pos + 1) % NUMBER;//环状处理
if (josephus[pos] == 0)
{
++flag;
}
if (flag == DEATH) //判断是否等于DEATH,等于DEATH则代表当前这个人要自杀
{
josephus[pos] = count;//将这个人是第几个自杀的记录到这个人这里
++count;//此时有人挂了,则自增1
flag = 0;//重置
break;
}
}while(true);
}
printf ("第一种解决办法的Josephus Problem每个人的自杀顺序为: \n\n");
for (int i = 0; i < NUMBER; ++i)
{
printf ("第%d个人的自杀顺序为:%d\t", (i+1), josephus[i]);
if ( (i%3) == 0 )
{
printf("\n");
}
}
printf ("\n\n\n");
}
//第二种方法,记录人数死亡的顺序
void secondFunction(int josephus[])
{
int order[NUMBER] = {0};//记录自杀顺序
int flag = 0;//标记报数的人数
int count = 0;//表示数组的下标
int pos = -1;
while (count < NUMBER)
{
do
{
pos = (pos + 1) % NUMBER;//环状处理
if (josephus[pos] == 0)
{
++flag;
}
if (flag == DEATH) //判断是否等于DEATH,等于DEATH则代表当前这个人要自杀
{
josephus[pos] = 1;//将这个人是第几个自杀的记录到这个人这里
order[count] = pos+1;//数组下标是从0开始算起的,所以要加1来表示人所在的位置
++count;
flag = 0;//重置
break;
}
}while(true);
}
printf ("第二种解决办法的Josephus Problem自杀顺序为: \n");
for (int i = 0; i < NUMBER; ++i)
{
printf("第%d个自杀的人的位置是:%d ", (i+1), order[i]);
if ( (i%3) == 0 )
{
printf("\n");
}
}
printf("\n");
}
int main()
{
int firstPeople[NUMBER] = {0}; //初始化数组,数组的下标代表的人的编号
firstFunction(firstPeople);
int secondPeople[NUMBER] = {0};
secondFunction(secondPeople);
return 1;
}