题目:
有n个人围成一圈,顺序排号。从第一个人开始报数(从1到m报数),凡报到m的人退出圈子,问最后留下的是原来第几号的那位。
解题思路:
1、阅读题目后可以知道这里涉及到循环,因为不是报数一轮就会停止,而是会一直报数。那么首先要考虑循环的终止条件,通读题目可知,最后只会剩一个人,可以作为循环的终止条件。
以最简单的三个人报数到三淘汰为例,首先编号为3的人会被淘汰,剩余两个人接着报数,编号为1的人第二个被淘汰,最后剩下的人编号为2。当n和m发生变化时,过程类似。
2、在循环中,首先要判断轮到的人有没有被淘汰,没有被淘汰的人才能报数。
报数又分为两种情况:
(1)报数报到m,此人会被淘汰(程序中令其编号归零),报数会从下一个人重新开始(报数统计归零),淘汰人数会加1。
(2)报数没有报到m,轮到下一个人(指针移动)。
3、无论上一个人报数情况如何,都该下一个人进行报数(指针向后移动)。如果移动后指针指向队尾,证明报数了一圈,那么应该重置指针指向队首,开始下一圈。
4、重复2、3过程,直到只有一个人没有被淘汰(唯一编号没有被归零的人),结束循环。
程序代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
int n,m,i = 0;
int *p = NULL;
printf("请输入有多少人参与:");
scanf("%d",&n);
printf("第几个报数的人会被淘汰:");
scanf("%d",&m);
int a[n];
p = a;
for(i = 0; i < n; i++){
a[i] = i+1;//给每个人编号
}
i = 0;//重置i的值
int count_1 = 0,count_2 = 0;//count_1用来记录报数,count_2用来统计淘汰的人
while(count_2 < n - 1) {//当淘汰的人达到n-1,即只剩最后一人时报数结束
if(p[i] != 0){//如果没有被淘汰的人就要报数
count_1++;
}
if(count_1 == m){//报到指定数字的人
count_1 = 0;//淘汰人后应该重新开始报数
p[i] = 0;//标记淘汰
count_2++;//记录淘汰人数
}
i++;//指向下一个人
if(i == n){//i只能先自增再判断,只有i++后i才可能得n
i = 0;//当指向队尾时,需要重置,使其重新指向队首
}
}
printf("最后的人起始编号为:");
for(i = 0;i < n;i++){
if(a[i] != 0){
printf("%d\n",a[i]);
break;//最后只会剩一个人,当找到第一个人后就可以推出循环
}
}
return 0;
}
运行结果:
请输入有多少人参与:8
第几个报数的人会被淘汰:3
最后的人起始编号为:7