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

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

题目

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

(PTA)报数:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m( 本题要求编写函数,给出每个人的退出顺序编号。

输入样例

10 3

输出样例

3 6 9 2 7 1 8 5 10 4 

解法一一般

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

#include
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
#include//队列头文件
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
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;
}

未完待续

你可能感兴趣的:(约瑟夫问题/报数问题的几种解法(学了新的再更新))