约瑟夫环问题的解法
递归法,迭代法,数数法,模拟法
问题描述
Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
有N个人围成一圈,顺序排号。从第一个人开始报数(从 1 到 M 报数),凡报到M的人退出圈子,问最后留下的是原来第几号的那位。
约瑟夫生者死者游戏
约瑟夫游戏的大意:30个游客同乘一条船,因为严重超载, 加上风浪大作,危险万分。因此船长告诉乘客,只有将全船 一半的旅客投入海中,其余人才能幸免于难。无奈,大家只 得同意这种办法,并议定30 个人围成一圈,由第一个人数起,依次报数,数到第9人,便把他投入大海中,然后再从 他的下一个人数起,数到第9人,再将他投入大海中,如此 循环地进行,直到剩下 15 个游客为止。问:哪些位置是将 被扔下大海的位置?
PY代码
# coding=utf-8
from functools import lru_cache
import sys
sys.setrecursionlimit(10**5) # 设置递归最大深度 10的5次方
@lru_cache(None)
def josephus(n, m):
if(n == 1):
return 0
else:
return (josephus(n-1, m) + m) % n
if __name__ == "__main__":
M, N = 3, 41
M, N = 9, 30
M, N = 3, 10
s = 0
ans = [0, -1]
for i in range(2, N+1):
s = (s+M) % i
for j in range(len(ans)):
ans[j] = (ans[j]+M) % i
if i < N:
ans.append(-1)
ans.reverse()
print(list(i+1 for i in ans), s+1, josephus(N, M)+1)
ans = []
live = [True]*N
i, j = 1, 0
while any(live):
if live[j]:
if i == M:
live[j] = False
i = 1
ans.append(j+1)
else:
i += 1
j += 1
if j == N:
j = 0
print(ans, "true")
ans = []
live = list(range(1, N+1))
i, j = 1, 0
while (live):
if i == M:
i = 1
ans.append(live[j])
del live[j]
if j == len(live):
j = 0
else:
i += 1
j += 1
if j >= len(live):
j = 0
print(ans, "del")
ans = [-1]*N
for i in range(1, N+1):
for j in range(i):
ans[j] = (ans[j]+M) % i
ans.reverse()
print(list(i+1 for i in ans), "累加ALL")
firstL = 6
ans = [-1]*N
lefts = N-firstL
for i in range(lefts, N+1):
for j in range(lefts, i):
ans[j] = (ans[j]+M) % i
ans.reverse()
print(list(i+1 for i in ans), "取前-1")
ans = [0]*N
lefts = N-firstL
for i in range(lefts, N+1):
for j in range(lefts, i):
ans[j] = (ans[j]+M-1) % i+1
ans.reverse()
print(ans, "取前0")
ans = [0]*N
lastN = 4
for i in range(0, N+1):
for j in range(0, i if i < lastN else lastN):
ans[j] = (ans[j]+M-1) % i+1
print(ans, "LastXu")
结果显示
[3, 6, 9, 2, 7, 1, 8, 5, 10, 4] 4 4
[3, 6, 9, 2, 7, 1, 8, 5, 10, 4] true
[3, 6, 9, 2, 7, 1, 8, 5, 10, 4] del
[3, 6, 9, 2, 7, 1, 8, 5, 10, 4] 累加ALL
[3, 6, 9, 2, 7, 1, 0, 0, 0, 0] 取前-1
[3, 6, 9, 2, 7, 1, 0, 0, 0, 0] 取前0
[4, 10, 5, 8, 0, 0, 0, 0, 0, 0] LastXu
递归法,迭代法,数数法,模拟法
及求前后单独序列的方法