Josephus环

来源:互联网 发布:mysql数据库认证考试 编辑:程序博客网 时间:2024/06/05 14:13

约瑟夫(Josephus)环问题

这一次谈一下笔试遇到很多次的约瑟夫环问题:

约瑟夫环问题即设有n个人坐成一个圈,从某个人开始报数,数到m的人出列,接着从出列的下一个人开始重新报数,数到m的人再次出列,如此循环,知道所有人都出列剩下最后一个人,最后按照出列顺序输出

这里给出的是三种解法:

  1. 数组法: (可以知道最后剩下的人及出列的顺序)
// 数组求解vector<int> Josephus(int n,int m){    vector<int> ans;            // 先出列的序号    int *a=new int [10000];   // 维持一个状态数组    int i;                     // 游标Token    int count=0;             //计算被退出的人数(n-1)    int t=0;                 //1,2,3..m报数记数变量    for(i=0;i<n;i++)        a[i]=i+1;    i = 0;      // 记得将i从头开始    while(count<n-1) //只剩下一个时退出循环    {        if(a[i]!=0){            t++;        }        if(t==m){            ans.push_back(a[i]);            a[i] = 0;            count ++;            t = 0;        }        i ++;        if (i ==n){            i = 0;   // Token重头开始        }    }    for(i=0;i<n;i++){       if(a[i]!=0)        {            printf("\n最后剩余的结点是:%4d\n",a[i]);        }    }    return ans;        }int main( ){    int n,m;    vector<int > ans;    cout<<"请输入结点的个数:"<<endl;    scanf("%d",&n);    cout<<"请输入报道报数周期是:"<<endl;    scanf("%d",&m);    ans = Josephus(n,m);    cout<< "先出队的顺序为:"<< endl;    for(int j = 0; j < ans.size(); j++){        printf(" %d ",ans[j]);    }    return 0;}

2 . 数学法:
(只可以知道最后的元素),参考网址:
[url]http://www.cnblogs.com/EricYang/archive/2009/09/04/1560478.html

* 递推公式 *

f[1]=0;

f[i]=(f[i-1]+m)%i; (i>1)

代码如下:

// 数学求解int main(int args, char ** argv){ int n , m ; scanf("%d%d",&n,&m); int s= 0 ; int i = 0; for (i = 2; i<= n; ++i){   s = (s+ m) % i; } printf("\n%d \n",s+1);}

3 . 循环链表法(可以知道最后剩下的人及出列的顺序)
代码也是上述的url解法

原创粉丝点击