约瑟夫环数组模拟循环列表实现

    halo各位看客老爷们大家好,今天我们要介绍的主题是约瑟夫环,那么什么是约瑟夫环呢?

    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。

    最近在做vj上题的时候发现了这个很有趣的问题,初次接触觉得与海豚算法也就是时间复杂度为O(n)的算法很像,实际上还是有很大的不一样,这次我们先上原题和代码,再来分析:

原题地址:http://noi.openjudge.cn/ch0302/1748/

#include<stdio.h>
#include<string.h>

int main () {
	int n,p,m;
	while(scanf("%d %d %d",&n,&p,&m)) {
		if(n == 0 && m == 0 && p == 0) {
			break;
		}
		int arr[1000] = {0};
		int print[1000] = {0};
		int step = 1;
		int count = 0;
		int temp = p-1;
		while(count < n) {
			//printf("1");
			if(step == m) {
				print[count] = temp + 1;
				count++;
				step = 0;
				arr[temp] = 1;
			}
			temp = (++temp)%n;
			if(arr[temp] == 0) {
				step++;
			}
			//printf("%d",step);
		}
		for(int i = 0;i < count-1;i++) {
			printf("%d,",print[i]);
		}
		printf("%d\n",print[count-1]);
	}
}

    首先我们要对基本操作进行分析,假设我们有n个人,从第p位开始,每次隔m位出队一个,问题本质也就是一个循环,循环次数是n,因为要出队n人,但实际上每次出队完一次以后都会使总人数减少一位,所以没有一个固定的公式能让我们快速的知道结果。因此,我们利用一个标记数组arr来标记该人是否已经出队,出队记为1,没出队记为0此外我们还需要一个临时变量temp来表示位置,以及step来表示已走的步数,需要注意的是,step在每次出队以后需要重置(提问!为什么第一次step的值为1,而不是每次重置后的0!)

    经过这些变量初始化后,我们的问题实际上就很明了了,在出队人数没有到达n之前,我们不断的重复右移的操作,如果temp位置上的人没有出队,我们令step++,表示走了一步,如果temp位置上的人已经出队,我们令temp++,step不变表示跳过,输出结果只需要一个记录数组来记录,最后输出即可。还有一个注意的点是temp =(++temp)%n这里,temp不能一直累加,当temp超过总数n时,我们可以对temp进行取余,来达到循环的目的。

最后是我们的测试结果:

是不是很简单呢!

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值