当前位置:首页 > C++目录 > 正文内容

【题解】围圈报数(约瑟夫问题)

亿万年的星光5年前 (2021-02-21)C++目录2426

【题目描述】

有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个热呢又出列,... ,如此反复到所有的人全部出列为止。设n个人的编号分别为1,2

,... , n,打印出列的顺序。

【输入描述】

一行,n和m。

【输出描述】

输出列的顺序

【样例输入】

4 17

【样例输出】

1 3 4 2

【题目分析与思路1】—数组

  1.  题目来源于“约瑟夫问题”。把所有人都放到数组中

  2. 每个人的状态有两个,出列或者不出列,可以用true和false表示

  3. 每个人一开始都在队列中,可以都用false表示

  4. 然后模拟出队列的过程,直到所有人都出队列

  5. 问题难点在于每个人出队后,队列就变了(长度变了),

  6. 在外部写个循环保证还有人在队伍里就继续

  7. 在上一个条件下,遍历数组,给选定的人进行标记,同时进行累加判断,找到第m个人。




约瑟夫.png


【参考代码1】

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int a[100]; //学生数组 
int n,m; // n个人,第m个人出列 
int main()
{
    int people,position;  //用people表示还在队列中的人,position表示每轮的计数情况,每次从0开始 
    cin>>n>>m; 
    for(int i=1;i<=n;i++)
        a[i]=1;  //先把所有的人都标记为1 
    
	people=n; //把所有人赋值给people 
    position=0;  
    while(people>0) // 只要还有人在队列中就继续 
    {
        for(int i=1;i<=n;i++)  //遍历n个人 
        {
            if(a[i]==1) //如果当前这个人是1,表示在队列中,就从中找第m个 
            {
                position++;  //位置加1 
                if(position==m) //如果是第m个位置 
                {
                    position=0;  // 把位置重置为0 
                    a[i]=0; //把当前这个人提出队列,下次就不再遍历他了 
                    cout<<i<<" "; //当前人编号输出 
                    people--;  //队列减去一个1 
                    if(people==0) //如果没人了,就退出 
                    {
                        break;
                    }
                }
            }
        }
    }
    return 0;
}




【题目分析与思路2】—队列

#include<iostream>
#include<queue>
using namespace std;
int main()
{
    int n,m;
    cin>>n>>m;  //读入n和m 
    
    queue<int> q;
    for(int i=1;i<=n;i++)
        q.push(i); 
        
    int cnt=0;
    while(!q.empty()){ //只要队列不为空 
        cnt++;  // 计数加1 
        int temp=q.front();  //把当前队首元素拿出 
        if(cnt==m){  //判断是不是到了m 
            cnt=0;  //把计算器变为0 
            cout<<temp<<" ";  // 输出这个人的编号 
        }
        else{
            q.push(temp); //表示还没到m 
        }
        q.pop(); //遇到第m个,就删除队首。没有遇到第m个,就把队首删除(队首已经重新入队变成队尾了) 
    }
    cout<<endl;
    return 0;
}






【链表版本】

#include <iostream>
using namespace std;
struct node {
	long d;
	node * next;
};
long n,m;
node *head,*p,*r;
int main() {
	long i,j,k,l;
	cin>>n>>m;
	head=new node;
	head->d=1;
	head->next=NULL;
	r=head;
	for(i=2; i<=n; i++) {
		p=new node;
		p->d=i;
		p->next=NULL;
		r->next=p;
		r=p;
	}

	r->next=head;
	r=head;
	for(i=1; i<=n; i++) {
		for(j=1; j<=m-2; j++)
			r=r->next;
		cout<<r->next->d<<" ";
		r->next=r->next->next;
		r=r->next;
	}
}


    扫描二维码推送至手机访问。

    版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

    分享给朋友:

    相关文章

    【数据结构】优先队列(1)

    优先队列(Priority Queue)是一种特殊的队列,它 不遵循“先进先出”(FIFO) 的原则,而是 按照优先级(Priority) 来出队。优先级高的元素 先出队,优先级低的元素 后出队。1....

    深搜剪枝技巧

    一、什么是剪枝     首先应当明确的是,“剪枝”的含义是什么。我们知道,搜索的进程可以看作是从树根出发,遍历一棵倒置的树——搜索树的过程。而所谓剪枝,顾名思义...

    【数论】均值不等式

    【数论】均值不等式

    均值不等式是高中常见的一个知识点,下面这篇文章做一下简单总结。1、其中a,b属于实数R,当且仅当a=b时,等号成立。这个也叫基本不等式2、其中a,b属于正实数,当且仅当a=b时,等号成立。3、其中a,...

    C++整型的数据范围

    数据类型标识符占字节数数值范围数值范围短整型short [int]2(16位)-32768~32767-2^15 到2^15  -1整型[long] int4(32位)-...

    C++ 中的常量

    C++ 中的常量

    一、说明常量和变量是相对的概念 —— 变量是 “能变化的量”,而常量就是一旦定义就固定不变、不能修改的值。用生活里的例子类比,你就能秒懂为什么需要常量:本质是 “给固定不变的东西贴‘只读标签’,避免误...

    二维数组的差分

    一、基本概念二维数组差分是一种高效处理区间修改操作的数据结构技巧,常用于解决矩阵区域增减问题。差分是前缀和的逆运算,对于二维数组,差分数组 diff[i][j] 表示原数组 a[i][j] 与 a[i...