今天老师布置了个题目,约瑟夫环,俗称猴子选大王。n个人报数,报到3的退出,最后留在场上的时原来的第几位
#include <stdio.h>
int main()
{
int i, n, q, p = 0; //计数 i ,人数 n ,报数 p ,场上人数 q
printf ("input number");
scanf ("%d", &n);
q = n;
int a[n];
for (i = 0; i < n; i++) //将1到n输入进数组a
{
a[i] = i+1;
}
for (i = 0; ; i++)
{
if (i == n) /*当i++一直到n时,肯定有一些没被选到,比如我们输入8,第一轮是3,6被赋值0,当i=8时,继续下一轮*/
{
i = 0;
}
if (0 != a[i]) /*我们下面定义的时当循环到三时,就赋值0,所以这边等于0的不考虑在内*/
{
p++;
}
else
continue;
if (0 == p%3) //这个就是从0一直加,到三的倍数就赋值为0,从而达到我们的目的
{
a[i] = 0;
q--; //上面q=n;标明q==n,只有一个为0就减一,为下面做铺垫
}
if (1 == q) //当剩下最后一个就输出
{
break;
}
}
for (i = 0; i < n; i++) //输出最后一个人的编号
{
if (0 != a[i])
printf ("spare:%d\n", a[i]);
}
return 0;
}
后来在网上又看到2种不同的方法,一种是用的指针
#include <stdio.h>
int main()
{
int i, j, k, m, n;
int *p;
printf ("input number");
scanf ("%d", &n);
int num[50];
p = num;
for(i = 0; i < n; i++)
{
*(p+i) = i + 1; //以1至n为序,给每个人编号
}
i = 0; //i为每次循环时计数变量
k = 0; //k为按1 2 3报数时的计数变量
m = 0; //m为退出人数
while(m < n-1) //当退出人数比n-1少时(即未退出人数大于1时)执行循环体
{
if(0 != *(p+i))
{
k++;
}
if(3 == k) //将退出人的编号置为0
{
*(p+i) = 0;
k = 0;
m++;
}
i++;
if(i == n)
{
i = 0;//报数到尾后i恢复为0
}
}
while(0 == *p)
{
p++;
}
printf ("最后一个是:%d\n", *p);
return 0;
}
还有个牛人的,代码很简练(装13)
#include <stdio.h>
int main()
{
int n, i, s = 0;
int M = 3;
printf ("input number");
scanf ("%d", &n);
for (i = 2; i <= n; ++i)
s = (s+M) % i;
printf("%d\n", s+1);
return 0;
}