约瑟夫问题(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;
}