约瑟夫环问题【队列实现,循环数组实现】

起源

约瑟夫环问题的起源来自犹太历史学家约瑟夫和他的朋友以及39其余的犹太人,总共41人为了躲避敌人,藏在一个山洞中,
39个犹太人决定宁愿死也不被敌人抓到,于是决定自杀,所有人排成一个圈,由第一个人开始报数,每当数到3,就自杀。
这个游戏接着从自杀的位置开始,还是从1数到3。依次类推,约瑟夫将朋友和自己安排在了16和31的位置,最后顺利逃过了
自杀这一劫,因为最后就剩他一个人了。

题目描述

n 个人围成一圈,从第一个人开始报数,数到 k 的人出列,再由下一个人重新从 1 开始报数,数到 k 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

输入

输入两个整数,n和m

输出

输出一行 n 个整数,按顺序输出每个出圈人的编号。

传送门

约瑟夫问题

思路1

我们可以用循环数组实现,数到指定的数过后,就标记为已出圈并且统计出圈人数,直到出圈人数等于所有人数。

代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int arr[105];
bool vis[105];
int main(){
	int n,k;
	scanf("%d%d",&n,&k);
	int i=0,j=0,num=0,cnt=0;
	while(true){
		j=i%n+1;
		if(!vis[j])	num++;//没走过就报数 
		if(num==k){//当报的数为指定值时,则标记为已出圈 
			num=0;
			cnt++;	
			vis[j]=true;
			printf("%d ",j);
			if(cnt==n)	break;
		}
		i++;
	}
	return 0;
}
 
思路2

我们也可以把这个题想象为是一个队列操作,先把每个数压入队列,然后从队头开始遍历,如果报数等于指定数,则弹出队列,否则压入这个数(压入则是在队尾),再弹出这个数,如果这里不理解,手画一遍,就能明白。

代码
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	queue<int>q;
	int n,k,num=1;
	cin>>n>>k;
	for(int i=1;i<=n;i++)	q.push(i);
	while(!q.empty()){
		if(num==k){
			cout<<q.front()<<" ";
			q.pop();
			num=1;
		}
		else{
			q.push(q.front());
			q.pop();
			num++;
		}
	}
	return 0;
}

当然如果题目求最后一个被杀死的人,我们还有效率更高,更巧妙地算法,链接在这里约瑟夫环

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值