约瑟夫环问题

来源:互联网 发布:java 实体类命名 编辑:程序博客网 时间:2024/05/16 01:49

转载来自:http://blog.csdn.net/sunandice/article/details/6560889

问题描述:约瑟夫环(Josephus)问题是[1]由古罗马的史学家约瑟夫(Josephus)提出的,他参加并记录了公元66—70年犹太人反抗罗马的起义。约瑟夫作为一个将军,设法守住了裘达伯特城达47天之久,在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴中避难。在那里,这些叛乱者表决说“要投降毋宁死”。于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的。约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品一起投降了罗马。 
 约瑟夫环问题的具体描述是:设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。

 

现在有两个具体的问题:

1、当任意给定n和m后,设计算法求n个人出圈的次序。  
2、求出最后出圈的那个人的序号。

 

解答:

1、我尝试着用数学方法来解决这个问题,但是没找到比较好的解法(主要是某个序号在前一阶段已经被删除了,这点不好记录)。因此还是用程序来解决吧。网上的代码很多,大意是构造一个循环链表,每经过一个数组元素,则将计数器数加1.当计数器加到m时,移除该链表元素,将计数器置为0,继续往下数。直到链表长度为1.移除元素的顺序即为n个人除权的次序。算法复杂度为O(nm).

 

2、这个问题可以用第一个问题的最后出列的序号来求解。但从数学上有更好的解法。每次去除一个元素后,将剩下的元素重新排序,用倒推的方法求出下一个出圈的元素在上一轮中的序号。从倒数第一轮一直推到第一轮,就能够直到胜利的那个元素的原先的序号。详情如下[1]:

 

 为了讨论方便,先把问题稍微改变一下,并不影响原意: 
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出 
,剩下的人继续从0开始报数。求胜利者的编号。 
我们知道第一个人(编号一定是m%n-1) 出列之后,剩下的n-1个人组 
成了一个新的约瑟夫环(以编号为k=m%n的人开始): 
   k   k+1   k+2   ... n-2, n-1, 0, 1, 2, ... k-2 
并且从k开始报0。 
现在我们把他们的编号做一下转换: 
k      --> 0 
k+1    --> 1 
k+2    --> 2 
... 
... 
k-2    --> n-2 
k-1    --> n-1 
变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这 
个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x 
变回去不刚好就是n个人情况的解吗?!!变回去的公式很简单,相 
信大家都可以推出来:x‘=(x+k)%n 
如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就 
行了。(n-2)个人的解呢?当然是先求(n-3)的情况 ---- 这显然就是 
一个倒推问题!好了,思路出来了,下面写递推公式: 
令f表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然 
是f[n] 
递推公式 
f[1]=0; 
f=(f[i-1]+m)%i;   (i>1) 
有了这个公式,我们要做的就是从1-n顺序算出f的数值,最后结 
果是f[n]。因为实际生活中编号总是从1开始,我们输出f[n]+1 
由于是逐级递推,不需要保存每个f,程序也是异常简单: 
#include <stdio.h> 
main() 

   int n, m, i, s=0; 
   printf ("N M = "); scanf("%d%d", &n, &m); 
   for (i=2; i<=n; i++) s=(s+m)%i; 
   printf ("The winner is %d/n", s+1); 

这个算法的时间复杂度为O(n).

 

 

[1]http://chenchuxin.iteye.com/blog/173518

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 换新手机后微信头像都没有了怎么办 苹果系统维护换不了微信头像怎么办 系统通知栏不显示qq图标怎么办 快递号码写错了而且发货了怎么办 包裹遗忘在郑州东站安检口了怎么办 锁书包的锁头钥匙全掉了怎么办 平板电脑恢复出厂设置变英语怎么办 给国外银行汇款账号写错账号怎么办 顺丰快递暴力运输产品坏了怎么办 亚航订机票名字少写一个字母怎么办 如果淘宝付款七天内不发货怎么办 浪琴手表调了一下日期不走了怎么办 收件人号码写错快递柜已签收怎么办 医院名字写错了怎么办保险报销 电脑在使用中出现了英文字慕怎么办 下雨天了怎么办我好想你是什么歌 安卓手机不支持微信运动怎么办 装系统时无法跳过密匙怎么办 在msdn里下的系统没有网怎么办 w7电脑更新后系统没法激活怎么办 手机使用加速器后网速变卡怎么办 奥特曼ol分解了迪迦石像怎么办 左右棋牌游戏兑换总说系统护怎么办 四季海棠扦插以后黄叶卷叶怎么办 竹节海棠浇水多了叶子蔫了怎么办 社保停缴了里面的钱怎么办 王者荣耀英雄释放技能有延迟怎么办 买的桑拿木板颜色太深了怎么办 万一填写了奔跑吧诈骗信息该怎么办 深圳限行时段堵在路上怎么办 开车堵在路上到了限行时间怎么办 兄妹之间都不想照顾母亲我该怎么办 小孩扁体发炎睡觉呼吸声沉重怎么办 客所思pk3老驱动有杂音怎么办 手机打不开解压包密码怎么办 在香港专柜买东西柜员少给货怎么办 恶魔猎手第二神器任务没选择怎么办 电脑放久了开不了机怎么办 你在主持时说错话了怎么办 1、你在主持时说错话了怎么办? 领导让你替他参加重要会议怎么办