约瑟夫环问题求解

约瑟夫问题分为两种类型

类型一

约瑟夫问题如下:

n个人围成圈,依次编号为1,2,..,n,现在从1号开始依次报数,当报到m时,报m的人退出,下一个人重新从1报起,循环下去,问最后剩下那个人的编号是多少?
input:
amount 队列人数
m 数到m时退出一个人

output:
最后一个退出的人的下标

思路:(用布尔数组做)
我们可以把这amount个人想象成是都是true的布尔数组,然后每次有个人找true的数组,是的话就往前进,一直进m个然后进行下一次操作,进了m次之后把m次到达的位置置为false. 如此循环往复,直到数组中只剩一个true为止

我下面的代码就是参照上面思路来写的。

#include <iostream>
using namespace std;
bool trek[1000];
void main()
{
    int amount,m;
    cin>>amount>>m;
    for(int i=1;i<=amount;i++){//对布尔数组赋初值
        trek[i] = true;
    }
    int num=amount;
    while(num!=1){  //数组只剩一个为true时退出
        int temp=0,count=0;//temp记录m,count对数组进行遍历
        while(1){       
            if(temp==m) { trek[count]=false;break;}
            count++;   //count位置很讲究,不放在这儿就错了
            if(count>amount) count-=amount;//循环
            if(trek[count]==true) temp++;
        }
        num--;
    }
    for(i=1;i<=amount;i++){   //输出
        if(trek[i] == true)
            cout<<i<<endl;
    }
}

类型二

类型二的约瑟夫问题就是在类型一的基础上修改了一点点,类型一是每次都是从1位置开始数,而类型二是每次从上一次之后的下一个位置开始数,因此类型二与类型一的代码大同小异。

在代码中计数是通过count变量完成的,而在类型一中每次找到一个就对count进行了重置,在类型二中代码只许不对count进行重置即可

代码如下:

#include <iostream>
using namespace std;
bool trek[1000];
void main()
{
    int amount,m,count=0;  //count在此处声明
    cin>>amount>>m;
    for(int i=1;i<=amount;i++){
        trek[i] = true;
    }
    int num=amount;
    while(num!=1){
        int temp=0;   //类型二中的count没有在此处重置
        while(1){       
            if(temp==m) { trek[count]=false;break;}
            count++;
            if(count>amount) count-=amount;
            if(trek[count]==true) temp++;
        }
        num--;
    }
    for(i=1;i<=amount;i++){
        if(trek[i] == true)
            cout<<i<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值