约瑟夫环问题

约瑟夫环问题

做题时遇到了类似问题,困扰了一会,就去查了一下,在此总结一下约瑟夫环问题

题目如下 :
n个人围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人从1开始报数…以此类推,直到最后一个人退出,依次输出退出圈的人的编号。

假设有n=10个人, 每次报数到m=3
编号: 1 2 3 4 5 6 7 8 9 10
报数: 1 2 3 1 2 3 1 2 3 1
因为报道3的人都退出,所以编号为3,6,9的人都退出
然后我们假设退出的人标记为1, 没退出的标记为0,就有:

编号: 1 2 3 4 5 6 7 8 9 10
报数1:1 2 3 1 2 3 1 2 3 1
标记1:0 0 1 0 0 1 0 0 1 0

第3,6,9个同学退出圈圈, 并将它们标记为1

继续接着最后一名同学报的数字继续报数:
第1名同学接着第10名同学的1报出了2,已经退出的同学跳过不报数
编号: 1 2 3 4 5 6 7 8 9 10
报数2:2 3 1 2 3 1 2
标记2:0 1 1 0 0 1 1 0 1 0

这一次,第2,7名同学退出圈圈,并将它们标记为1


报数3:3 1 2 3 1
标记3:1 1 1 0 0 1 1 1 1 0

报数4: 2 3 1
标记4:1 1 1 0 1 1 1 1 1 0

报数5: 2 3
标记5:1 1 1 0 1 1 1 1 1 1

所以最后一个退出的是第4个数字

最后,代码如下:

# include <stdio.h>
int main(void)
{
	int a[100] = {0};
	int i = 0; // 每个同学的编号;如果有 10 个人,那第 7 名同学的编号 i = 7; 
	int k = 0; // 报的数字 1,2,3,1,2,3,1,2,3; 
	int n = 0;//有 n 名同学; 
	int s = 0; // 出列同学的个数; 
	scanf("%d", &n);
	while(s != n){ //直到出列同学的人数和所有同学的个数相等时循环结束; 
		i++;	//每次循环i+1,就是另一个人报数; 
		if(i > n)  //如果同学的编号大于总人数,就重新从第一个同学开始,相当于一个圈圈; 
		i = 1; 
		if(a[i] == 0){ //a[i] == 0时,说明这些同学没有出列,继续报数; 
			k++;	//报数的值会加 1 
			if(k == 3){//当报的数字为 3 之后,再让它从 1 开始报数 ,并且将该同学标记为 1 ,表示出列; 
				a[i] = 1;//出列 
				s++;//出列的同学个数 + 1 ; 
				k = 0;  
				printf("%d ", i); //输出出列同学的编号; 
			}
		}
	} 
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值