题目描述
有n个人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
题目分析
这便是整体的题目流程,大家围成一个圈,愉快的报着数,报到3的人直接out,下一个小伙伴再次从一开始报起,直到我们的决赛圈:
在这也是恭喜我们的m+x号同学获得游戏胜利,可他究竟是谁呢?这也正是我们编程所要解决的目标。
编程解决
做这道题的思路其实也正是我们用代码来把整个游戏过程表示出来,让电脑来帮我们依次报数、淘汰、找出决胜者。
接下来是函数原型:
int remind(int n){} //形参n传入参加此次游戏的总人数,用int返回值来返回胜利者编号
为了解决游戏人数由n传入,存储大小未定的问题我们需要用到C语言动态分配的知识,来定义一个动态数组并且给他们依次赋上编号。
而且此题中我们会发现一个关键性的变量,那就是各个玩家所报出来的数字,我们用这个数字来淘汰每个报数报到3的玩家,在这里我们将他命名为tag,同时,我们还需要一个变量来记录淘汰玩家的个数,当淘汰个数到达n-1的时候游戏结束,胜利者也就诞生了,于是我将这个变量命名为out。
int* circle = (int*)malloc(n * sizeof(int)); //生成动态数组来对应每位玩家的状态
int tag = 1; //当前报数号
int out = 0; //游戏淘汰人数
for (int i = 1; i <= n; i++) //为每一位游戏成员挂上编号
circle[i - 1] = i;
同时,我们需要一个循环来不断地进行报数操作,并且完成每位成员依次报数与报到3即淘汰的操作,循环到淘汰玩家到n-1个时退出循环:
int i = 0; //用于遍历每一位成员
while (out != n - 1) //循环到淘汰人数达到n-1人
{
if (circle[i] == -1) //如果该成员已被淘汰则不参与计数
{
if (i == n - 1)
i = 0;
else
i++;
continue;
}
if (tag == 3) //如果报数为3,将此成员淘汰,将淘汰人数加1,并且将报数号重置
{
circle[i] = -1; //淘汰则将此成员编号赋为-1以示淘汰
out++;
tag = 1;
if (i == n - 1)
i = 0;
else
i++;
continue;
}
tag++; //正常(人员未被淘汰参与报数且报数不为3)状况代码段
if (i == n - 1)
i = 0;
else
i++;
}
对玩家数组的操作已经完毕,接下只需确定返回值内容即可,接下来直接展示完整代码。
全部代码
#include<stdlib.h>
int remind(int n)
{
int* circle = (int*)malloc(n * sizeof(int));
int tag = 1;
int out = 0;
for (int i = 1; i <= n; i++) //初始化数组
circle[i - 1] = i;
int i = 0; //用于遍历每一位成员
while (out != n - 1)
{
//如果该成员已被淘汰则不参与计数
if (circle[i] == -1)
{
if (i == n - 1)
i = 0;
else
i++;
continue;
}
//如果报数为3,将此成员淘汰,将淘汰人数加1,并且将报数号重置
if (tag == 3)
{
circle[i] = -1;
out++;
tag = 1;
if (i == n - 1)
i = 0;
else
i++;
continue;
}
//正常(人员未被淘汰参与报数且报数不为3)状况代码段
tag++;
if (i == n - 1)
i = 0;
else
i++;
}
//确定返回值
i = 0;
while (circle[i] == -1)
i++;
free(circle);
return i+1;
}
(如有问题,欢迎指正)