您的位置:首页 > 其它

Jesephus problem ( 小议约瑟夫家的问题 )

2014-04-17 10:14 162 查看
    问题描述:编号为1~n共n只猴子坐成一圈想要选大王,大家约定从1开始报数数到n的猴子退出,剩下的猴子继续从1开始报数,直到剩下最后一只猴子时,它就被选为大王。

    有一种常规的解决思路:模拟选大王的过程。用一个长度为n数组作为标志数组,将每次退出猴子对应编号上标记为FALSE,继续报数,遇到标记为false的元素跳过继续,直到数组中只剩一个标记为true的数组,其就是大王。时间复杂度O(mn)。

    为了感性认识,请大家考虑一种极端情况,如果n为100只,最后只剩下2只标记为true的猴子,我们为了得到大王,本只需在2只猴子间进行报数,谁最先报出m,则淘汰。但是程序的做法却需要将100个猴子扫描m-1次进行m-1计数,直到报出m。是不是很复杂?

    为了得到大王,我们得拿出我们数学这把利剑,采用递推方式,只需要时间复杂度为O(n)就能解决问题。下面细细道来

   
递推方法:递推,顾名思义从猴子少的时候推到猴子多的时候,找其中的规律。因为习惯我们把编号设成0~n-1,对于上面问题求解时,我们再将编号加一就是了。以下取m=3进行说明。

   f(i):表示当猴子数量为i时,猴王的编号。例如:f(1)=0,当只有一只猴子时,其编号为0,它肯定就是猴王了。f(2)=1,两只猴子从编号为0开始报数,报数为3的猴子退出,很明显猴王编号为1。下面给出猴子依次变化时,猴王变化情况:

    


    发现规律了f(i)=(f(i-1)+m)%i.对这就是我们需要的。那么要求猴子总数为n的时候,已知初始值f(1)=0,又有了递推公式,是不是很简单了。

    再拓展下,我们能不能得到n只猴子依次出队的序列呢,如果这个知道,那儿我们就可以很容易算出编号为i的猴子是第几次出队的,是吧?

    咱们继续找规律吧。f(i)下面对应了一列数,从下往上,表示当猴子总数为i时,依次出队的先后顺序。

    



    
   是不是发现了?每个标蓝色的数字其对应的一行数字之间仍然是满足(f(j)+m)%i【采用(j)只是为了与猴王的f(i)避免冲突】,但是我们不知道递归的初始值啊,即:蓝色数字怎么求呢?有以下两个方案:

   1)对于f(i)序列中共有0,1··i-1个数,我们如果已经知道除了蓝色数以外的数字,通过搜索排除就能知道蓝色数

   2)针对每个f(i)序列和我们能算出,用其减去已递推了的数,就能知道蓝色数了

   时间复杂度为O(n*n).

   代码已传到CSDN,希望大家多多批评指正。

       

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息