首页 > 其他 > 详细

算法----约瑟夫环问题

时间:2014-03-12 01:41:00      阅读:408      评论:0      收藏:0      [点我收藏+]

约瑟夫环是一个数学的应用问题:

已知n个人(以编号0,1,2, ... n-1 分别表示)围坐在一张圆桌周围。从编号为0的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。求最后一个出列的人的序号。。


方法 1:

模拟游戏。利用数组或者循环链表,模拟游戏的进行,直到最后仅仅留下一个数。

复杂度是 O(MN)


方法 2: O(N)

1. 一开始,n 个人: 0  1  2  3   ...     m-1   m   m+1 ... n-1     显然,编号 m-1 的人出列;

                                                             ||

                                                             \/

2.            新的序列:0  1  2  3 ...  m-2        m   m+1 ... n-1     从 编号 m 开始新的一轮游戏,

                                                              ||   因为从编号m开始,把后半段放到前面

                                                              \/         

                                 m   m+1   ...  n-1       0      1      2   ...   m-2

                                                              ||   编号变换 <1>, 右半部分加上 n

                                                              \/

                                 m    m+1  ...   n-1      n     n+1   n+2 ...  n-m-2

                                                              ||  编号变换 <2>, 全部减去 m

                                                              \/

                                 0    1   2   3  .......X .............    n - 2

假设红色数字 X 是 [ 0 1 2 ... n-2] 中最终存留的序号,我们的目标是得到这个编号经过了两次编号变换前的编号 x‘。

两次编号变换的逆变换其实就是                   x‘  = ( X + m) % n;

因此,我们得到了递推关系式   f [n] = ( f[n-1] + m ) % n;

代码如下:

// copyright @ L.J.SHOU Mar.11, 2014
// jossef circle
#include <iostream>
#include <vector>
using namespace std;

int JosefCircle(int m, int n)
{
  vector<int> f(n+1, 0);

  for(int i=2; i<=n; ++i)
    f[i] = (f[i-1] + m) % i;

  return f[n];
}


算法----约瑟夫环问题,布布扣,bubuko.com

算法----约瑟夫环问题

原文:http://blog.csdn.net/shoulinjun/article/details/21042237

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!