题目
题目描述 :
n个猴子围坐一圈并按照顺时针方向从1到n编号,从第s个猴子开始进行1到m的报数,报数到第m的猴子退出报数,从紧挨它的下一个猴子重新开始1到m的报数,如此进行下去知道所有的猴子都退出为止。求给出这n个猴子的退出的顺序表。
输入:
有做组测试数据.每一组数据有两行,
第一行输入n(表示猴子的总数最多为100)
第二行输入数据s(从第s个猴子开始报数)和数据m(第m个猴子退出报数).
当输入0 0 0时表示程序结束.
输出:
输出中,每组数据的输出结果为一行,中间用逗号间隔。
样例输入:
10
2 5
5
2 3
0
0 0
样例输出:
6,1,7,3,10,9,2,5,8,4
4,2,1,3,5
话不多说,先上代码
#include <stdio.h>
int main()
{
int s, m, n;
int a1 = 1;
int a[105] = { 0 };
int i1, i2;
int s1, m1, s2;
int j, j1, j2;
while (a1)
{
scanf("%d", &n); //猴子总数;
scanf("%d%d", &s, &m);//s:从第s个猴子开始报数,m:第m只猴子退出;
i2 = 1;
if (n == 0 && s == 0 && m == 0)
{
a1 = 0;
}
else
{
for (i1 = 0;i1 < n;i1++)
{
a[i1] = i2;
i2++;
}//初始化,用1-n的数字代表猴子;
s1 = s - 1;
m1 = m - 1;
//因为是用数组来代表猴子,由于数组是从0开始计数的,则s需减1;
while (n > 0)
{
s1 = (s1 + m1) % n;
printf("%d", a[s1]);
for (j = 0;j < n;j++)
{
if (j == s1)
{
j1 = s1;
while (j1 < n)
{
j2 = a[j1];
a[j1] = a[j1 + 1];
a[j1 + 1] = j2;
j1++;
}//将报过数的猴子移除
}
}
if (n > 1)
{
printf(",");
}
else
{
printf("\n");
}
.
n--;
}
}
}
return 0;
}
分析
由题意可知,每只猴子的座位是固定的,而且每次报数完毕后又会重新开始报数,故我们可以利用数组来解决此题。那问题又来了如何用数组来完成这样一个报数的过程呢?可能有细心的小伙伴已经发现了只要我们能够得到退出那只猴子所对应的是数组里第几个,这样这道题也就迎刃而解了。
难点一 : 如何得到每次退出的猴子是所对应的数组里的第几个
从题目可知,它是从某一个数开始,数固定个数后剔除一个数。
eg: 五个数:1,2,3,4,5
从1开始,数到3停止。即,每数两个数( 3 - 1 = 2),剔除一个数。则出来的属的顺序为:
3,1,5,2,4
用数组来解决:
即:1,2,3,4,5,分别对应:a[0],a[1],a[2],a[3],a[4]
此处若延用之前的思路是很难完成的,但有一个比较便捷的方法:s = (s + m) % n;
(具体为什么我也不清楚,如果有知道的uu可以在评论区解释一下吗?谢谢!)
将对应的s , m,的数组位次代入会发现刚好是要输出的的那个数。
见代码如下:
s1 = s - 1;
m1 = m - 1;
//因为是用数组来代表猴子,由于数组是从0开始计数的,则s需减1;
//
while (n > 0)
{
s1 = (s1 + m1) % n;
难点二 : 如何在数组中表示剔除的数(或猴子)
其实也不难,在数组中可以将要剔除的数移到数组的最后以为以表示除出去
代码如下:
while (n > 0)
{
s1 = (s1 + m1) % n;
printf("%d", a[s1]);
for (j = 0;j < n;j++)
{
if (j == s1)
{
j1 = s1;
while (j1 < n)
{
j2 = a[j1];
a[j1] = a[j1 + 1];
a[j1 + 1] = j2;
j1++;
}//将报过数的猴子移除
}
}
此处仅是截取部分代码,详细请见前面代码
小编自语
以上代码只是个人的一点见解,仅供大家参考。当然有可以改进的地方可以在评论区写下,让大家一起学习学习。关注小编,让我们一起学习进步吧!