今天老师布置了个题目,约瑟夫环,俗称猴子选大王。n个人报数,报到3的退出,最后留在场上的时原来的第几位
#include <stdio.h>int main()
{int i, n, q, p = 0; //计数 i ,人数 n ,报数 p ,场上人数 qprintf ("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;
}