这里的代码都是博主在pta亲测过的没一定没有问题,小伙伴可放心使用。
报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
先代码后解析
本题要求编写函数,给出每个人的退出顺序编号。
函数接口:void CountOff( int n, int m, int out[] );
答案一:
void CountOff( int n, int m, int out[] )
{
int item=n,i,num=0,j=1;
int s[MAXN];
for(i=0;i<n;i++)
s[i]=i+1;
while(item)
{
for(i=0;i<n;i++)
{
if(s[i]!=0)
{
num++;
if(num==m)
{
s[i]=0;
out[i]=j;
item--;
j++;
num=0;
}
}
}
}
}
- 我们用item来控制循环的是否继续执行,因此这里的item表示的是还在圈内的人数,我们将传入的参数n赋值给item。并在每次弹出一个小伙伴的时候对item进行自减,那么在若剩余人数为0则循环结束。
- 弹出的处理思路,通过if条件句和一个变量num来控制是否在某个循环是否提出这个人,如果提出则将这个单元赋值为0.这样就可以在for循环下设置是否要进行操作的判断语句if(s[i]!=0)。
- 我们前面的数组s[MAX]只是为了配合for下面第一个if条件赋值,这里其实可随意赋值,只要让他满足全部不等于零即可。
答案二
void CountOff( int n, int m, int out[] )
{
int i,count=0,j=0,item=0;
for(i=0;i<n;i++)
out[i]=0;
i=0;
while(1)
{
if(out[i++]==0)
count++;
if(count==m)
{
item++;
out[i-1]=item;
count=0;
}
if(item==n)
break;
i=i%n;
}
}
-
此算法与上一个算法思路并不相同。这里我们先定义一个长度为n数值全为0的数组。之后我们在while循环里对这个数组进行操作。
-
这里可能有小伙伴会疑惑为什么要用out[i++],这样写的话,后面还得改成out[i-1]=item,博主解释一下,这里纯粹是个人习惯,我这样写的话,后面不必考虑i自加的情况。当然小伙伴大可以,在这里把自加省略掉,在后面重新写一行自加。
-
顺带说一下,我们在c语言中使用i++与++i是不一样的。一张图可以直观的告诉大家:
很显然。i++为先用后加,而++i为先加后用。这些基本的东西,小伙伴们还是要掌握的 -
这里的item表示弹出的顺序数。
-
最后的i=i%n,这里有必要讲一下,因为博主在这里懵了一会。我们都知道小数取模大数,得到的就是这个小数,博主刚开始很困惑为什么,这里要进行一个不必要的操作。后来才想通,我们观整个while循环,在自己的思路里跑一下就会发现,这个循环的次数很大,当我们输入参数11 3的时候它都可以循环42次,而在这些过程中i是不断自加的,也就说到了第11次循环的时候,i已经大于n了,这时候我们要对他取模才能保证,i可以一直在1~11之间进行循环,从而判断。