/*
一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第3(可以拓展到m)只,把它 踢出圈,从它后面再开始数,再数到第3(可以拓展到m)只,在把它踢出去…, 如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入n 输出最后那个大王的编号。用程序模拟该过程。请输出猴王是一只;
如输入 11
输出为 7
*/
#include <stdio.h>
int main(void) {
/*后一个和前一个报数不同;
本程序为默认设计为 依次报数为1 2 3修改部分参数(注释中将指出)后可以用于其他报数的情况*/
int all;
scanf("%d", &all);//这是C99支持的方式
int sit[all];//生成all只猴子
int tell;//用来给每一只猴子记录某一次猴子 报到1 或 2或 3(即tell的取值为1 or 2 or 3)
int i;//用来循环数组用的记步变量
i = 0;
for (; i<all; i++) {
sit[i] = 0;//将得到的数组中所有元素赋值为0(数组元素为0 代表该猴子还活着)
}
int now = all;//now表示现在还没被淘汰的猴子总数
for (; (now != 1);) {
/*因为最后只会有一只猴王
所以这个循环在 只有一个为0 的元素的时(即只剩下一只没有被淘汰) 跳出*/
for (i = 0; i<all; i++) {
if (sit[i] == 0 && tell == 3) {
/*判断 当这只猴子还没被淘汰(元素值为0) 而且此次报数为3(tell值为3)
如果将3 改成N 则报数为1-N*/
sit[i] = 1; //将这只猴子淘汰(元素赋值为1)
now = now - 1;//未被淘汰的猴子数减少1
tell = 1;//将这个口号调到1 给下一只猴子报数
}
if (sit[i] == 0) {
/*注意 !!! 这里有两种情况:
1.如果没有(判断通过后进入上面的if 语句时 则将口号(tell)加1
2.如果进入了 上面的if语句后 则 这个语句一定不会进入(因为在前面已有sit [i] = 1)*/
tell++;
}
}
}
if (all == 1 || all == 2) {//程序设计的时候 考虑的是猴子数大于3只
if (all == 1) {
printf("1");//猴子数为1 自然第一只 是猴王
}
else {
printf("2");// 猴子数为2 自然第二只 是猴王
}
}
else {
for (i = 0; i<all; i++) {
if (sit[i] == 0) {/*这里通过遍历整个数组(猴群),找到那一个没有被淘汰的猴子(即 i 的值)*/
printf("%d ", i);
}
}
}
return 0;
}