约瑟夫问题

  在古罗马人占领乔塔帕特后,39个犹太人与约瑟夫和他的朋友躲到一个洞中。39个犹太人决定宁死也不被敌人抓到,于是商定以一种特殊的方式自杀:

  41个人排成一个圆圈,由第一个人开始报数,每报数到3的人就必须自杀,直到所有人都自杀身亡为止。

  但是约瑟夫和他的朋友并不想死,那么请问,约瑟夫和他的朋友,应该怎样安排自己的位置,才能逃过一劫?

  分析:如果约瑟夫和他的朋友不想死,那么他们将是最后剩下的两个人,因此,问题的关键在于如何安排他们的位置,才能将他们留到最后。

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(f'总共{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]

因此,如果约瑟夫和他的朋友如果想要逃生,就得把自己和朋友放到第16和第31个位置上,以保证他们是最后的两个玩家

 

posted on 2019-10-04 15:31  wintalau  阅读(499)  评论(0编辑  收藏  举报

导航