约瑟夫问题/报数问题的几种解法(学了新的再更新)

本文介绍了约瑟夫问题及其变种“报数”问题的三种编程解法:一般解法使用数组记录状态,队列解法则利用C++标准库中的队列进行模拟,而vector解法通过动态数组和erase函数实现人员的逐个淘汰,适用于小规模数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

约瑟夫问题/报数问题的几种解法

题目

(洛谷)约瑟夫问题:n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

(PTA)报数:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
本题要求编写函数,给出每个人的退出顺序编号。

输入样例

10 3

输出样例

3 6 9 2 7 1 8 5 10 4 

解法一一般

由于这两个平台里这个题目给的数据很小,所以可以直接c或者c++

#include<iostream>
using namespace std;

int n,m,i,j,k,p[105];//主函数外定义,默认为0;
//p数组记录在(0)或不在(1),
int main(void)
{
	cin>>n>>m;
	i=n;
	while(i){//全部退出则循环结束;
		j++;
		if(j>n)	j-=n;
		if(p[j]==0)	k++;
		if(k==m){
			cout<<j<<" ";
			p[j]=1;
			k=0;
			i--;
		}
	}
	return 0;
 } 

解法二队列

运用C++的队列进行模拟,简单愉悦;

#include<iostream>
#include<queue>//队列头文件
using namespace std;
int main()
{
    int n,m,k=1;
    queue<int>q;
    cin>>n>>m;
    for (int i=1;i<=n;i++)	q.push(i);//排入队列
                                      //q.push将元素压入队尾
    while(!q.empty())//在队列不为空时继续模拟
                     //q.empty队列为空时true,反之false
    {
        if (k==m)
        {
            cout<<q.front()<<" ";//输出
            q.pop();//删除队首元素但不返回
            k=1;
        }
        else
        {
            k++;
            q.push(q.front());//排至队尾
                              //q.front返回队首元素但不删除
            q.pop();
        }
    }
    return 0;
}

解法三vector

还是C++,运用vector动态数组,erase使得我们可以丢一个删一个

#include<bits/stdc++.h>
using namespace std;
int main(void){
	int n,m;
	cin>>n>>m;
	vector<int>no;
	for(int i=1;i<=n;i++)
		no.push_back(i);//在尾部插入一个元素;
	int num=0;
	while(no.size()!=0)
	{
		num=(num+m-1)%no.size();
//上面公式简单的解释,动态数组删去一个元素后,之后的下标都会减一
		cout<<no[num]<<" ";
		no.erase(no.begin()+num);
	}
	return 0;
}

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值