约瑟夫环问题求解

来源:互联网 发布:男生休闲鞋推荐 知乎 编辑:程序博客网 时间:2024/04/29 14:34

约瑟夫问题分为两种类型

类型一

约瑟夫问题如下:

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
原创粉丝点击