约瑟夫环问题(C语言)

      约瑟夫问题(Josephus Problem)又称约瑟夫环,其定义如下:n 个人围成一圈,对其顺时针编号为 1~n,然后从第 1个人开始顺时针方向报数,第1个人报数 1,第2个人报数 2,以此类推,凡报数k的人则出列,接着下一个人重新从1开始报数,如此反复例如n=8,k=3,则出列的顺序是 3、6、1、5、2、8、4、7。

第一步:

首先利用宏创建一个数组,先初始化为0,接着输入n和k,我们假设1是在队列中的人,0表示已出列。利用循环先给数组赋值n个1,即开始时场上有n个人。

#pragma warning(disable:4996)
#include <stdio.h>
#define N 100

int main()
{
	int peo[N] = {0};
	int n = 0;//人数
	int k = 0;//出列的数字
	int i = 0;
	int count = 0;//用来报数
	int count_1 = 0;//用来计数是第几个出列
	printf("请输入人数:");
	scanf("%d", &n);
	printf("请输入需要出列的数字:");
	scanf("%d", &k);
	for (i = 0; i < n; i++)
	{
		peo[i] = 1;
	}

第二步:

首先这是一个环,假设n=10,所有人都没出列的话,实际上报数1的人和报数11的是同一个人,这就有个周期性,当我的i大于人数后就应该减去n。

然后是判断如果i对应的那个人在场的话就应该报数,即peo[i] == 1的话,count就应该++。然后如果那个人报的数就等于k的话,那他就出列了,他对应的数组的值也就变成了0,就代表他出列了,之后count = 0,因为要重新开始报数。(别忘了人对应的序号和数组的下标是差了1的)

	for (i = 0; i < 100; i++)
	{
		if (i > n-1)
		{
			i = i - n;
		}
		if (peo[i] == 1)
		{
			count++;
			if (count == k)
			{
				count_1++;
				printf("第%03d个出列:%d号\n", count_1,i+1);
				peo[i] = 0;
				count = 0;
			}
		}
	}

完整代码

#pragma warning(disable:4996)
#include <stdio.h>
#define N 100

int main()
{
	int peo[N] = {0};
	int n = 0;
	int k = 0;
	int i = 0;
	int count = 0;//计数
	int count_1 = 0;
	printf("请输入人数:");
	scanf("%d", &n);
	printf("请输入需要出列的数字:");
	scanf("%d", &k);
	for (i = 0; i < n; i++)//将场上存在的人用1表示
	{
		peo[i] = 1;
		//printf("%d ", peo[i]);
	}
	for (i = 0; i < 100; i++)
	{
		if (i > n-1)
		{
			i = i - n;
		}
		if (peo[i] == 1)//如果这个人在场上,他就要报数
		{
			count++;
			if (count == k)
			{
				count_1++;
				printf("第%03d个出列:%d号\n", count_1,i+1);
				peo[i] = 0;
				count = 0;
			}
		}
	}
	return 0;
}

运行结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈陈陈陈某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值