[算法]Josephus问题--报数游戏

问题描述:

N个人围成一圈,按顺序排号。从第一个人开始报数(从1开始),凡报到5的人退出圈子,问最后留下的是原来第几号的那位。

例如:9个人围成一圈,1号从第1开始报数,5号首先退出圈子。接着6号从1开始重新报数,1号退出圈子。接着2号从1开始重新报数,7号退出圈子。然后从8号开始重新报数,4号退出圈子。6号重新报数,3号退出圈子。依次类推,最后剩下原来的8号留下

  1. 已有文件in.txt。输入文件格式如下:

    656

    786

    547

    9

    3423

  2. 文件里每一行为一个整数N,表示每一轮游戏有N个人参与报数。以回车换行。
  3. 输出最后留下的人员编号

解题:理解题目后发现,这是一个Josephus问题,总共包含n个人,从第k(K=1)个人开始数数,数m个之后退出,依次循环

首先需要将n个人映射到一个长度为n的数组中people[0]...people[n-1]对应[1,n],注意下标和编号的对应(编号1的下标为0),针对约瑟夫问题,两种方法:

1.数组标记方式:扫描数组,设置计数器,当数到m时,将对应的值设为0(退出),将计数器复位,进行下一轮的计数,直到剩下最后一个元素:

需要注意:经过几轮的访问之后,数组的下标可能已经超过了数组长度,需要将数组下标取模映射到原数组中

2.列表方式:扫描数组,如果数到m时,则将对应的数从列表中出列,直到数组长度变为1

#数组方式,n:数组长度,k:开始编号,m:数的个数;
def josephus_A(n,k,m):
    people = list(range(1,n+1))
    i = k - 1
    for num in range(n):
      count = 0   #count:计数器
      while count < m:
        if people[i] > 0:
          count += 1
          if count == m:
             print(people[i],end=' ') #退出的人
             people[i] = 0  #编号设为0
          i = (i+1)%n
        if num < n - 1:
             print(", ",end="")
        elif num == n - 1: 
             print("最后留下:",people[i])
        else:
             print(" ")
    return

def josephus_L(n,k,m):
    people = list(range(1,n+1))
    num, i = n, k-1
    for num in range(n-1,0,-1):
        i = (i+m-1)%num
        print(people.pop(i),
              end=(", " if num > 1 else "\n"))
    print("最后留下:",people[0])
    return

#测试
with open(filename,'r',encoding='utf-8') as fp:
    lines = fp.readlines()
    for line in lines:
        line = line.rstrip('\n')
        n = int(line)
        k = 1
        m = 5
        josephus_A(n,k,m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值