1 约瑟夫问题描述
在古罗马人占领乔塔帕特后,39个犹太人与约瑟夫和他的朋友躲到一个洞中。39个犹太人决定宁死也不被敌人抓到,于是商定以一种特殊的方式自杀: 41个人排成一个圆图,由第一个人开始报数,每报数到3的人就必须自杀,直到所有人都自杀身亡为止。但是约瑟夫及其朋友并不想死,那么请问约瑟夫及其朋友应该怎样安排自己的位置才能逃过一劫?
2 问题分析
如果约瑟夫及其朋友不想死,那么他们将是最后剩下的两个人,因此,问题的关键在于如何安排他们的位置才能将他们留到最后。
3 Python程序模拟
下面我们用程序模拟这个自杀过程,找出最后两个人的位置,这两个位置就是约瑟夫及其朋友的位置。
def move(man,sep):
"""
将man列表向左移动sep单位,最左边的元素向列表后面添加,相当于队列顺时针移动
"""
for i in range(sep):
item = man.pop(0)
man.append(item)
def play(man=41,sep=3,rest=2):
"""
man:玩家个数
sep:杀死数到的第几个人
rest:幸存者数量
"""
print('总共%d个人,每报数到第%d的人自杀,最后剩余%d个人'%(man,sep,rest))
man=[i for i in range(1,man+1)] #初始化玩家队列
print("玩家队列:",man)
sep-=1 #数两个数,到第3个人时就自杀
while len(man)>rest:
move(man,sep)
print('kill',man.pop(0))
return man
servive=play()
print("最后逃生的人编号是:",servive)
测试及运行结果如下:
总共41个人,每报数到第3的人自杀,最后剩余2个人
玩家队列: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41]
kill 3
kill 6
kill 9
kill 12
kill 15
kill 18
kill 21
kill 24
kill 27
kill 30
kill 33
kill 36
kill 39
kill 1
kill 5
kill 10
kill 14
kill 19
kill 23
kill 28
kill 32
kill 37
kill 41
kill 7
kill 13
kill 20
kill 26
kill 34
kill 40
kill 8
kill 17
kill 29
kill 38
kill 11
kill 25
kill 2
kill 22
kill 4
kill 35
最后逃生的人编号是: [16, 31]
Process finished with exit code 0
因此,约瑟夫和他朋友如果想要逃生的话,就得把他自己和朋友放到第16和31个位置上,以保证他们是最后的两个玩家。