P1996 约瑟夫问题

题目背景
约瑟夫是一个无聊的人!!!

题目描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.

输入格式
n m

输出格式
出圈的编号

输入输出样例
输入 #1复制
10 3
输出 #1复制
3 6 9 2 7 1 8 5 10 4
说明/提示
m,n≤100

参考代码1.0: 用队列构成环,目的元素输出后删除,非目的元素插入队尾,即构成了一个环;
图解: k从1开始,不是3的时候就将其插入队尾,图上显示则是1排到9的后面,2排到1的后面。。。。

在这里插入图片描述

#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAX 5010

using namespace std;

int main()
{
    int n, m;
    int pos = 1;
    cin >> n >> m;
    queue<int> q;
    for(int i = 1; i <= n; i++) q.push(i);
    while(!q.empty())
    {
        if(pos == m)
        {
            cout << q.front() <<" ";
            q.pop();
            pos = 1;
        }
        else
        {
            pos++;
            q.push(q.front());
            q.pop();
        }
    }

    return 0;
}
参考代码2.0: 用数组构成环,用k记录间隔,用pos记录下标,pos的变化为:pos = (pos+1)%n;可以保证成环循环;pos遇到为0值时,直接跳过直接后移,退出条件为输出数已到达n;
注意:k的初值为1,原因如图:

1、假设输入为n = 10, m = 3; k 开始时就已经指向了第一个元素,所以从1开始,清零的位置是第一组m的最后一个元素,还没开始下一组,所以清零;
2、与上一个不同,上一个输出直接删除,k仍然从1开始,但是k的指向到了输出的下一个,而数组只是清了零,指向的还是输出元素的位置。
在这里插入图片描述

#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAX 5010

using namespace std;

int S[101];

int main()
{
    int n, m;
    //num累计输出个数,pos记录下标的变化,k记录间隔(从1开始)
    int pos = 0, k = 1,num = 0;
    cin >> n >> m;
    for(int i = 0; i < n; i++) S[i] = i + 1;
    while(num < n)
    {
        if(k == m)
        {
            cout << S[pos] <<" ";
            S[pos] = 0;
            //累计num,清零k
            num++; k = 0;
        }
        else
        {
            k++; pos = (pos+1) % n;
            //若为0,则跳过,继续后移
            while(S[pos] == 0)  pos = (pos+1) % n;
        }
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值