算法-约瑟夫环问题——python实现

发布于:2022-12-10 ⋅ 阅读:(739) ⋅ 点赞:(0)
Hello NanFeng

遇到了一个有点意思的题:

一艘船上有30个人,现在因为超载需要15人下船,决策者采用了一种很特殊的抽签方式
1.先让人们排成一列,按照顺序给每个人编号
2.依次从1开始报数,数到7的人下船
3.有人下船后,从下船之人原来的位置下一个开始重新报数
4.这样一直重复这个步骤,直到船上剩下15人
请问哪些编号的人下船了,并告知下船顺序,以及最后哪些人留了下来

其实这本质上就是经典的约瑟夫环问题。

约瑟夫环问题

背景:故事源自著名犹太历史学家Josephus,在罗马人占领乔塔帕特后,39个犹太人与Josephus以及他的朋友躲进了一个山洞中,39个犹太人决定宁死不屈,于是决定了一个自杀方式,41个人排成一个圈,由第一个人开始报数,每数到3此人就自杀,然后由下一个重新报数,直到所有人都自杀为止。然而Josephus和他的朋友并不想这就死去,于是Josephus让他的朋友和他佯装遵从,他偷偷将朋友和自己安排在第16个和31个位置,最终逃过了这场死亡游戏。

python实现

我们只需要关注三个参数:
1.人的总数:total_nums
2.出局数值:step
3.需要出局的人数:out_nums

所以我们可以直接写出一个约瑟夫环问题的通用解法

def Josephus_dead_game(total_nums, step, out_nums):
    queue = list(range(1, total_nums + 1))
    cur_out_nums = 0
    while cur_out_nums < out_nums:
        print(f'{queue[step-1]} is out')
        queue = queue[step:] + queue[:step - 1]
        cur_out_nums += 1
    queue.sort()
    print(f'{queue} are the survivors')


def main():
    total_nums = int(input("请输入总人数:"))
    step = int(input("请输入你出局的报数为几:"))
    out_nums = int(input("请问总共要出局多少人:"))
    # 需要判断条件是符合逻辑,因为活下来的人不可能小于出局报数-1,所以 总人数 - 出局步数 + 1 >= 出局人数
    if total_nums - step + 1 >= out_nums:
        return Josephus_dead_game(total_nums, step, out_nums)
    else:
        print('\033[31m存活人数不得小于出局报数-1\033[0m')


if __name__ == "__main__":
    main()

我进行了一个逻辑判断,因为活下来的人数+1必定大于等于出局报数的数值,否则在需要的出局的人数还未达到预期值时,存活的人已经不够报到出局报数了。

测试发现,解法成立
本题条件:

请输入总人数:30
请输入你出局的报数为几:7
请问总共要出局多少人:15
7is out
14is out
21is out
28is out
5is out
13is out
22is out
30is out
9is out
18is out
27is out
8is out
19is out
1is out
12is out
[2, 3, 4, 6, 10, 11, 15, 16, 17, 20, 23, 24, 25, 26, 29] are the survivors

2.背景故事下的条件

请输入总人数:41
请输入你出局的报数为几:3
请问总共要出局多少人:39
3 is out
6 is out
9 is out
12 is out
15 is out
18 is out
21 is out
24 is out
27 is out
30 is out
33 is out
36 is out
39 is out
1 is out
5 is out
10 is out
14 is out
19 is out
23 is out
28 is out
32 is out
37 is out
41 is out
7 is out
13 is out
20 is out
26 is out
34 is out
40 is out
8 is out
17 is out
29 is out
38 is out
11 is out
25 is out
2 is out
22 is out
4 is out
35 is out
[16, 31] are the survivors

3.测试逻辑不成立的条件的情况

请输入总人数:41
请输入你出局的报数为几:3
请问总共要出局多少人:40
存活人数不得小于出局报数-1

就好比还是出局步数为3,但是只有约瑟夫一个人想活,但是会在累计出局第39个人时,剩下的人无法再数到三,所以逻辑无法成立(当然这是严格遵守游戏规则的情况下,如果你说最后的人自觉点别管那么多都自杀就行了我也没办法哈哈哈哈哈哈)
根据 ‘活下来的人数+1必定大于等于出局报数的数值’ 这条规则,所以可以知道只想要有一个人存活那出局步数最大只能是2

请输入总人数:41
请输入你出局的报数为几:2
请问总共要出局多少人:40
2 is out
4 is out
6 is out
8 is out
10 is out
12 is out
14 is out
16 is out
18 is out
20 is out
22 is out
24 is out
26 is out
28 is out
30 is out
32 is out
34 is out
36 is out
38 is out
40 is out
1 is out
5 is out
9 is out
13 is out
17 is out
21 is out
25 is out
29 is out
33 is out
37 is out
41 is out
7 is out
15 is out
23 is out
31 is out
39 is out
11 is out
27 is out
3 is out
35 is out
[19] are the survivors
Hello NanFeng
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到