Josephus problem(约瑟夫问题)

本文详细介绍了著名犹太历史学家Josephus所经历的一个自杀游戏的算法解决方案,通过两种方法解决了这个问题,并提供了详细的代码实现。游戏规则为41个人排成一圈,从第一个人开始报数,每报数到第三个人该人就必须自杀,直到所有人都自杀身亡。Josephus和他的朋友通过巧妙的策略成功逃脱了这场死亡游戏。
摘要由CSDN通过智能技术生成

       据说著名犹太历史学家 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; 
 }
  
  


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值