7-28 猴子选大王 (20分)

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

输入格式:

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

输出格式:

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

输入样例:

11

 

输出样例:

7

这道题的考点就是约瑟夫环,看到了一组巨简洁的代码

#include<stdio.h>

int main(void)
{


 //表达每数到3就退一个

int N = 0;
int sum = 0;

scanf("%d", &N);

for(int i = 2; i <= N; i++)
    sum = (sum + 3) % i;

printf("%d", sum + 1);

return 0;
    


}

约瑟夫环问题,这是一个很经典算法,处理的关键是:伪链表
问题描述:N个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,报到m的人出圈;如此往复,直到所有人出圈。(模拟此过程,输出出圈的人的序号)

 

void joseph(int count, int doom) {
int alive = count; //幸存人数
int number = 0; //计数,当number==doom时,淘汰这个人
int index = 0; //下标,为总人数-1
int *circle = NULL; //根据需求设为循环数组,存储每个人
//用calloc()函数申请得到的空间,自动初始化每个元素为0
//所以,0表示在这个人在约瑟夫环内,1表示这个人出圈,即“淘汰” 
circle = (int *) calloc(sizeof(int), count);

//只要幸存人数大于0,则一直进行循环 
while(alive > 0) {
	number += 1- circle[index];	//每轮到一个人报数,不管是"0"还是"1"都进行计数 
	if(number == doom) {		//当number==doom时,就要淘汰当前这个人
		/*
			淘汰一个人需要做四步操作:
				1、输出这个人的位置 
				2、把这个人的状态从在圈内"0"改为不在圈内"1" 
				3、幸存人数alive-- 
				4、 计数器number归零 
		*/ 
		alive == 1 ? printf("%d", index+1) : printf("%d,", index+1);
		circle[index] = 1;
		alive--;
		number = 0;
	}
	//与总人数count取余,则可以使index在0~count-1之间 一直循环,达到循环数组的目的 
	index = (index +1) % count;	
}
printf("\n");

free(circle);		//结束后一定要释放circle所申请的空间 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值