约瑟夫之问(约瑟夫问题(PASCAL))
今天哈哈娱乐网给各位分享李约瑟难题如何解答的知识,其中也会对约瑟夫之问(约瑟夫问题(PASCAL))进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在我们开始吧!
什么是约瑟夫问题
假定在圈子里前K个为好人,后K个为坏人,你的任务是确定这样的最少M,使得所有的坏人在第一个好人之前被杀掉。
什么是约瑟夫斯问题?
这是一个古老的传说:有64名战士被敌人俘虏了,敌人命令他们排成一个圆圈,编上号码1,2,3,…,64,敌人把1号杀了,又把3号杀了,他们是隔一个杀一个这样转着圈杀,最后剩下一个人,这个人就是约瑟夫斯,请问约瑟夫斯是多少号?这就是“约瑟夫斯问题”。
这个问题是比较容易解答的:敌人从1号开始,隔一个杀一个,第一圈把奇数号码的战士全杀死了。剩下的32名战士需要重新编号,而敌人在第二圈杀死的是重新编排的奇数号码。
由于第一圈剩下的全部是偶数号2,4,6,8,…,64。把它们全部用2除,得1,2,3,4,…,32,这是第二圈重新编的号码,第二圈杀过之后,又把奇数号码都杀掉了,还剩下16个人,如此下去,可以想到最后剩下的必然是64号。
64=26,它可以连续被2整除6次,是从1到64中能被2整除次数最多的数,因此,最后必然把64号剩下,从64=26还可以看到,是转这6圈之后,把约瑟夫斯剩下来的。
如果有65名战士被俘,敌人还是按上述方法残杀战士,最后剩下的还是64号约瑟夫斯吗?
不是了,因为第一个人被杀后,也就是1号被杀后,第二个被杀的必然是3号,如果把1号排除在外,那么剩下的仍是64个人,对于剩下这64个人,新1号就应该是原来的3号,这样原来的2号就变成新的64号了,所以剩下的必然是原来的2号。
对于一般情况来说,如果原来有2k个人,最后剩下的必然是2k号;如果原来有2k+1个人,最后剩下的是2号;如果原来有2k+2个人,最后剩下的是4号……如果原来有2k+m个人,最后剩下的是2m号。
比如,原来有100人,由于100=64+36=26+36,所以最后剩下的是2×36=72号;又比如,原来有111人,由于111=64+47=26+47,所以最后剩下的是2×47=94号。
下面把问题改一下:不让被俘的战士站成圆圈,而排成一条直线,然后编上号码,从1号开始,隔一个杀一个,杀过一遍之后,然后再重新编号,从新1号开始,再隔一个杀一个,问最后还是约瑟夫斯吗!
答案是肯定的,最后剩下的仍然是约瑟夫斯。
如果战俘人数是65人呢?剩下的还是约瑟夫斯,只要人数不超过128人,也就是人数小于27,那么最后剩下的总是约瑟夫斯,因为从1到128中间,能被2整除次数最多的就是64,而敌人每次都是杀奇数号留偶数号,所以64号总是最后被留下的人。
约瑟夫问题的问题来历
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
*问题分析与算法设计
约瑟夫问题并不难,但求解的方法很多;题目的变化形式也很多。这里给出一种实现方法。
题目中30个人围成一圈,因而启发我们用一个循环的链来表示,可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个人开始对还未扔下海的人进行计数,每数到9时,将结构中的标记改为0,表示该人已被扔下海了。这样循环计数直到有15个人被扔下海为止。
约瑟夫问题是怎么来的?有什么典故吗?
约瑟夫问题(PASCAL)
monkey:array[1..20] of integer;
i,j,k,n,m,x:integer;
begin
readln(n);
m:=2;
k:=n;
for i:=1 to 20 do monkey[i]:=i;
i:=1;
repeat
x:=0;
for j:=1 to (m div 2) do if m mod j:=0 then x:=1;
if x=1 then begin
i:=i+m-1;
for j:=i+1 to n do monkey[j-1]:=monkey[j];
n:=n-1;
end;
m:=m+1;
until k=1;
然后你自己把输出做一下;
约瑟夫问题
约瑟夫问题~~
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。
如若本站内容侵犯了原著者的合法权益,可联系本站删除。
如若转载,请注明出处:http://www.hahasou.com/ent/6109726ad.html