约瑟夫问题(Josephus Problem)

背景
     相传公元一世纪著名犹太历史学家约瑟夫在罗马人占领乔塔帕特後,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

约瑟夫问题描述
      设有n个犯人坐成一个圈(编号1~n),从第k(1<=k<=n)个人开始报数,数到m的人将被处决掉,接着从下一个人开始从新报数,数到m的人再被处决,如此循环,直至剩下一名犯人. 求处决犯人的顺序和最后的幸存者编号.
      我们可以用代码模拟整个过程从而得出正确的答案:

模拟法

    当然, 这并不是最好最高效的解法.这里我们回到广义的约瑟夫问题来分析一下:
    如果有n个人围成一圈而坐,每个人的位置都带编号,编号从1到n(没有重复的),从第k个位置开始数数,当数到m时,那个人退出圈子,再从退出的那个人的下一个位置开始数(假定是顺时针数的),一直到剩下r个人。

进一步分析

    n个人玩这个游戏的时候,假设最后剩下的r个人中,其中一个人占据了第p个位置,那当我们以n + 1个人开始玩游戏的时候,显然,这第n + 1个人希望被安排到第p + m个位置,因为如果第p个人是安全的,那么至少这第(p + m)MOD (n + 1)个位置上的人也是安全的,他的理由是“既然现在是n + 1个人玩,仍然只能留r个人,那么只要在n个人剩余的r个人里面有一个人在我之前退出就可以了,所以我要加在这第r个人中某个人的后面m处”。对应的,如果n个人玩的时候,第q个位置上的人退出了圈子,那n + 1个人玩的时候第(q + m)MOD (n + 1)个位置上的人也得退出圈子。根据前面的递推公式,显然我们可以通过逆推得到最终解,原先的约瑟夫函数可以写成如下形式:

代数法
      

推论
      从上面的分析中已经知道,每次添加一个人到游戏中,原来剩余的那r个人的位置就会“后移”m个单位,因为新加的人使得ta之前的第m个人退出了圈子。所以我们可以进一步地作出这样的推论:

假设n个人玩游戏,最后一个幸存者(即r = 1时)占据了编号为p的位置,而在n + x个人玩的时候,最后一个幸存者占据第y个位置。那么y = (p + mx )MOD (n + x)。
      这样我们就可以根据不同的初值n迅速计算出最后一个人的位置了。

参考资料
      1.W.W.Rouse Ball and H.S.M.Coxeter, Mathematical Recreations and Essays, Dover, 1987 
      2.Wikipedia,Josephus Problem,http://en.wikipedia.org/wiki/Josephus_problem

黄季冬
2009年8月4日
 

posted on 2009-08-04 14:35  J.D Huang  阅读(2013)  评论(2编辑  收藏  举报