17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
Ⅰ.数组
思路:
1.开一个数组,把每个人都放进去,每个人所在的数组位置都初始化为0.(一共n个人,数到m出去)。
2.定义cnt,表示目前已经出局的人数。
3.报数做一个循环,循环条件是cnt!=n。
#include<stdio.h>
int main()
{
int n, m, i, count = 0, num = 0;
int a[100]={0};
scanf("%d\n%d", &n, &m);
for (i = 1; i <= n; i++) {
a[i] = i;
} //存入编号
for (i = 1; ; i++) {
if (a[i] != 0) {
num++; // num记录已出局的人数
if (num == m) {
count++;
if (count == n) {
break;
}
printf("No%d: %d\n", count, a[i]);
a[i] = 0;
num = 0;
} // 报数为 m 出圈:
//出圈人数加一,输出编号,编号清零,计数器清零
}
if (i == n) {
i = 0;
}
}
printf("Last No is: %d", a[i]);
return 0;
}
Ⅱ.递归实现(这个最简洁)
有n个人,报到数字k出局,第i个人出局的编号。
假如有10个人 报到3出局
第一个出局的ysf(10,3,1)=2;旧环第二个出局的ysf(10,3,2)=5;
新环第一个出局的ysf(9,3,1)=2,即旧环的第二个可以由新环的第一个+3推算而来。
ps:以防加的数超过总人数,给ysf%n即可。
#include<stdio.h>
int ysf(int n,int k,int i) //n个人,报到k出去,第i个人的编号是
{
if(i==1)
return (n+k-1)%n;
else
return (ysf(n-1,k,i-1)+k)%n; //防止编号越界
}
int main() //测试用例
{
int k=3;
int n;
scanf("%d",&n);
printf("%d",ysf(n,3,n)+1);
return 0;
}
Ⅲ循环链表
这个俺不会,就是知道有这个方法。
等我学了再给兄弟萌哔哔~~