7-28 猴子选大王---数学的约瑟夫环问题思考

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

在这里插入图片描述
在网上学习别人的解题经验的时候看到这样一个C语言版本的解法,代码如下:

#include<stdio.h>
int main(){
  int n,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所申请的空间 

}

原文:https://blog.csdn.net/weixin_38214171/article/details/80352921

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值