约瑟夫环问题--

来源:互联网 发布:防蚊虫 知乎 编辑:程序博客网 时间:2024/06/05 19:38

之前碰到约瑟夫环问题草草了事,今天下午花了4个小时,把这个问题认认真真的看了几遍,总算是搞明白了。

问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。


我觉得首先要搞清楚的一个问题是  第一个出局的人 是编号为 m%n

假如有10个人(编号0--9,n=10)围成一个圈,从0开始报数,报到2(3-1,m=3)出局。第一轮出局者编号为(m-1)%n。(最好自己推算下)

(m-1)% n = (3 - 1) % 10 = 2。

剩下9个人 从编号3开始 从0开始报数,到2的出局。第二轮是把 第一轮编号为3的人编号为0,然后开始游戏(这句话很重要)

我们可以 假设n-1个人围成一个圈, 最后编号为f(n-1)的人胜出,

那么 对于n个人围成的一个圈,最后出局的人的编号为 f(n-1) +(m-1)%n + 1,因为第一轮编号为(m-1)%n的人出局,第一轮编号为(m-1)%n+1

的人开始从0报数,所以可以推出最后编号为f(n) = f(n-1)+(m-1)%n+1的人胜出

整理得

f(n) = (f(n-1)+m)%n (n>1)


(如果上面的分析 你还是 没看明白  建议你多读几遍 ,直到理解为止)

所以我们的代码可以这样写

int fun(int m, int n){     int i , res = 0;     if ( n == 1 )         return res;     if ( n > 1 )     {          for ( i = 2; i <= n; i++ )          {                res = ( res + m ) % i;          }          return res;     }      return -1;}

算法复杂度O(n)


参考资料:

http://www.cnblogs.com/woodfish1988/archive/2007/02/18/652251.html


原创粉丝点击