2037:【例5.4】约瑟夫问题

9 篇文章 0 订阅

2037:【例5.4】约瑟夫问题

题目描述

N N N个人围成一圈,从第一个人开始报数,数到 M M M的人出圈;再由下一个人开始报数,数到 M M M的人出圈;…输出依次出圈的人的编号。

输入格式

输入 N N N M M M

输出格式

输出一行,依次出圈的人的编号。

输入样例

8 5

输出样例

5 2 8 7 1 4 6 3

提示

数据范围

对于所有数据, 2 ≤ N , M ≤ 1000 2 \le N,M \le 1000 2N,M1000

思路

这一题约瑟夫问题可以用多种方法求解,如容器

AC代码如下

数组模拟

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n,m,j,a[1010],sum=0,i=0;//j计数变量,数m个数
	cin>>n>>m;
	memset(a,1,sizeof(a));//a[1010]全为1
	while(i!=n) { //重复执行n次
		j=0;
		while(j<m) {//讲未出圈的人进行循环
			sum++;
			if(sum>n)sum=1;//要是超出n,sum继续从1数起
			if(a[sum]!=0)j++;//计算人数
		}
		a[sum]=0;//讲sum设为已出圈,输出sum
		cout<<sum<<" ";
		i++;
	}
}

队列

#include<bits/stdc++.h>
using namespace std;
int main() {
	queue<int> q;//定义队列q
	int n,m,i=1;
	cin>>n>>m;
	for(i=1; i<=n; i++) {
		q.push(i);
	}//给圈里的每一个人编号
	i=1;
	while(!q.empty()) {//如果所有人没有全部出圈
		int l=i;
		for(; i<l+m-1; i++) {//进行数数,数m-1次
			q.push(q.front());//将队首放入队尾来模拟报数
			q.pop();//删除队首
		}
		cout<<q.front()<<' ';//输出报到m的人
		q.pop();//删除报到m的人
	}
	return 0;
}

容器

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n,m,i=1;
	cin>>n>>m;
	vector<int> q;//定义容器q
	q.clear();//将q清空
	for(i=1; i<=n; i++) {
		q.push_back(i);
	}//给圈里的每一个人编号
	i=1;
	while(!q.empty()) {//如果所有人没有全部出圈
		int l=i;
		for(; i<l+m-1; i++) {//进行数数,数m-1次
			q.push_back(q.front());//将容器之首放入容器之尾来模拟报数
			q.erase(q.begin(),q.begin()+1);//删除容器之首
		}
		cout<<q.front()<<' ';//输出报到m的人
		q.erase(q.begin(),q.begin()+1);//删除报到m的人
	}
	return 0;
}

链表

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int main() {
	int n,m;
	cin>>n>>m;//输入n、m
	for(int i=0; i<n; i++) //初始化
		a[i]=i+1;
	a[n]=1;
	int p=0;
	for(int i=1; i<=n; i++) { //开始模拟出圈过程
		for(int j=1; j<m; j++)
			p=a[p];//p位置右移
		cout<<p[a]<<" ";//输出出圈人的位置
		a[p]=a[a[p]];//删掉出圈人
	}
	return 0;
}

再见,记得三连哦!

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值