南开百题难题破解(5)

本文聚焦南开大学经典百题中的约瑟夫环问题,深入探讨其数学原理与解题策略,揭示环形序列中删除元素的规律,为解决此类复杂算法提供思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
题目要求:
设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数, 
报数到第m个人, 此人出圈, 再从他的下一个人重新开始1到m的报数,如此进行下
去直到所有的人都出圈为止。现要求按出圈次序,给出这n个人的顺序表p。请考生
编制函数Josegh()实现此功能并调用函数WriteDat()把编号按照出圈的顺序输出到OUT.DAT文件中。
设 n = 100, s = 1, m = 10进行编程。
题目解析:
约瑟夫环有好多种解法,但是大体的可以分为两类:
1. 将符合出圈要求的人进行标注,但是不出圈,只是下次再轮到此人时,直接跳过,不参加报数
2. 将符合出圈要求的人直接出圈(从环中删除),剩下的人继续报数。
这里列的是第二种方法,删除的方法是把该元素放到数组中的最后一个位置上,在出圈元素的后边的
元素,都向前移动一位
实现如下:

*/

void Josegh(void)
{
	int i;
	int count;//count当做数数的变量
	int people=n;//定义没有出圈的人数
	int tem;//存放出圈人的编号
	int j;
	//为这100个人进行编号
	for(i=0;i<n;i++)
	{
		p[i]=i+1;
	}
	i=0;
	count=1;//数数的下标从零开始,count从1开始。也就是说以i为下标的编号,正是count所数的编号,count和i是同时增加的。
	//在还没有人出圈之前,people=100,每出圈一个人people-1。当只剩下一个人的时候循环停止。
	while(people>1)
	{
		i=i%people;//已经出圈人的下标不再计算之内,也就是说数到数组中最后一个没有出圈的编号的时候,i重新指向0
		count=count%m;//count数到9的时候再从零开始数
		//count数到10的时候count的值为0,执行下面的if语句
		if(count==0)
		{
			//下面的循环将出圈的人之后的编号往前移动一位,出圈的人的编号放在p数组中的最后一位,视为出圈,同时人数减少一个
			tem=p[i];
			for(j=i;j<people-1;j++)
			{
				p[j]=p[j+1];
			}
			p[j]=tem;
			people--;
			count++;//根据题意,count重新开始数数的位置是当前位置
		}
		i++;
		count++;
	}	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值