PTA 猴子选大王 (约瑟夫环问题)

题目描述:

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

输入格式:

输入在一行中给一个正整数N(≤1000)。

输出格式:

在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

思路分析:

  1. 这是一道类约瑟夫环问题。可以把圈子大小创建为一个数组,并把每只猴子初始值赋值为1,当猴子报到3退出圈子时数值变为0。这个数值改变过程每执行一次,k加1,当k == N-1时,即出局人数k,剩余人数为1,游戏结束。
  2. 而约瑟夫环问题,可以简单化为数组重复从0到N-1的执行。在循环中添加判断条件,把数值为0的数组元素跳过。当遇到数值为1的元素,执行if的语句块,在语句块通过count计数,当count == 3,数值变为0,k++,count重新计数,变为0。
  3. 当数组下标移动到最大值时,数组重新循环,可以理解为数组头尾相接,即一个环,而count计数并不受影响,仍然可以想象为一个圈相接报数。

代码:

#include <stdio.h>
int main()
{
	int N, i, count = 0, k = 0, flag = 0;
	//count计数作为报数,是否为3的判断。k计算出局人数,当人数剩余1即可结束。flag标记最后一只数值为1的猴子。 
	scanf("%d", &N);
	int n[N]; //创建一个与猴子人数相同的数组,每个元素代表一只猴子。 
	for(i = 0; i < N; i++)
		n[i] = 1; //当猴子仍参与报数游戏时,数值为1,当猴子出局后,数值为0,以此判断该猴子是否参与报数游戏。 
	while(k != N-1) //当k == N-1,即剩余人数为1,该猴子为大王,游戏结束。 
		for(i = 0; i < N; i++)
			if(n[i] == 1) //n[i]等于0的猴子,则跳过,不参与报数。 
			{
				flag = i; 
				count++; //每一只猴子报数,count加1。 
				if(count == 3) //当n[i]猴子报到count==3。 
				{
					n[i] = 0; //猴子出局。 
					k++; //出局人数加1。 
					count = 0; //count重新报数。 
				}	
			}
	//可以简单理解循环条件只是判断游戏是否继续,循环过程是重复for循环执行,即数组下标重复移动,头尾相接。 
	printf("%d", flag+1); //因为数组从0开始。 
	return 0;
}

解释的会比较详细,觉得好可以多多关注点赞

发布了2 篇原创文章 · 获赞 2 · 访问量 42

猜你喜欢

转载自blog.csdn.net/jenny_jack/article/details/104427998