约瑟夫环问题
本文档基于简单的python知识来解决约瑟夫环问题
一、问题描述
故事版本较多,看起来略有不同,但实际上是殊途同归,问题本质都是一样的。本次研究主要针对其中一种故事版本。故事内容如下:
罗马帝国时期,犹太士兵被罗马人包围,为了不当俘虏,决定集体自杀。自杀的方式是所有人围成一个圈,第一个士兵杀掉他左边的第二个士兵,第三个士兵杀掉第四个士兵,第五个士兵杀掉第六个士兵。以此类推,直到最后只剩下一个人,然后他在自杀。
在这群犹太士兵里面,有个叫约瑟夫的人,他想投降保命,那么他应该站在什么位置,才能成为最后一个剩下的人,这样就可以不用自杀,直接投降。
二、问题解析
军队人数未知,可以自定义。
首先把问题减化,我只考虑前三个人的情况,后面他们怎么杀,我不关心。
我只看前三个人。首先可以确定的是,第一个人会杀死第二个人。
也就是说,无论是谁,只要站在第二个位置上,就必须死。这是解决问题的关键。
那么既然第一个人已经杀了一个了。他现在可以歇一会,给我滚回到队尾,去当最后一个人。
然后现在重新排序,刚刚第三个人,晋升到第一的位置了。刚刚第四个人晋升到第二的位置了。
所以新序列的第一个人就要把第二个给杀死,然后他也得滚回队尾,休息着。
以此类推,第一个人杀第二个,第二个出局,第一个去到队尾。然后重新排序。
继续由第一个人杀第二个,最后杀掉只剩下一个人,就结束了
三、python实现
#约瑟夫环问题
'''
问题分析
1、假设总共n个人,给1-n,这n个人进行编号,存储在一个列表中
2、从列表起始位置开始数数,数到第2个人,把他踢出去
3、把第1个人移到列表末尾,形成一个新的列表,新列表的第1个人,其实就是上一个列表的第3个人
4、继续重复步骤2和3,直到剩余人数为1,输出此时新列表第1个人对应编号
'''
def fun(man): #定义fun()函数
lst=[i for i in range(1,man+1)] #根据总人数生成列表[1,2,3......n]
#print(lst)
if man==1 or man==2: #总人数为1或者2,直接判定第一个人存活
print('幸存者为:',lst[0],'号')
else:
a=man #定义a为剩余人数
while a>1:
lst.append(lst[0]) #在列表末尾添加第一个人
lst.pop(1) #删除列表第二个人
lst.pop(0) #删除列表第一个人
a=a-1 #人数减少1
print('幸存者为:',lst[0],'号')
#输入总人数(总人数是大于等于1的正整数)
man=int(input('请输入总人数:'))
fun(man)
四、总结
假如总人数是100,运行程序,输入总人数:100,得到生存的位置是:73号
使用上面的程序,无论人数多少,总能求出生存的位置