OJ :Joseph 问题

 这道题目的意思就是:假如输入3,那么就代表有6个人,然后1,2,3是好人,5,6,7就是坏人

前面一半是好人,后面一半是坏人。然后你要指定一个m,m代表的意思就是你要隔多少个人杀一次人,然后m必须满足,第一个好人,也就是1 必须在所有坏人被杀之后才能杀。说白了就是5,6,7死完了,1才可以死。你的目标是找到那个最小的m

思路如下

1.先来看一个josefu简单代码的实现(核心思想就是找到current 然后pop(current)) 下面的例子就是我分析题目用的例子

#encoding=utf-8
def josefu(n,k):
    #n表示总人数 k表示每次杀人的间隔
    #准备一个porple列表存储n个人
    people=list(range(1,n+1))
    #current表示数到哪儿来了,值得注意的就是crrent是数组下标所以要从0开始
    current=0
    while len(people)>1:
        #计算出下一个被杀的人的位置
        current=(current+k-1)%len(people)
        #根据current杀人
        people.pop(current)
    return people[0]
print(josefu(6,5))

 2.根据题目的意思就是,1肯定只能在后半个k中死,如果前半个k中出现1肯定就不对,那就不需要再继续判断了(用这个条件可以减少一点时间)

3.我的大体思路就是从0开始枚举m,然后利用josefu把每次杀的人记录下来,只要把后k个人都枚举了,而且这个时候1还没死,最先出现这种情况对应的m就是我们要找的那个m

4.只要把后k个人都枚举了,而且这个时候1还没死(再准备一个坏人列表存储k个人,每杀一个人如果是坏人就pop一个直到为空,就停止杀人返回m)(同时准备一个好人列表存k个好人,保证在坏人k列表为空之前,1没有被pop出去就ok了)

#encoding=utf-8
def josefu(n,k):
    #n表示总人数 k表示每次杀人的间隔
    #准备一个porple列表存储n个人
    people=list(range(1,n+1))
    #current表示数到哪儿来了,值得注意的就是crrent是数组下标所以要从0开始
    current=0
    while len(list_badman)>0:
        #计算出下一个被杀的人的位置
        current=(current+k-1)%len(people)
        #根据current杀人
        killed=people.pop(current)
        if killed in list_goodman:
            return False
        if killed in list_goodman:
            list_goodman.remove(killed)
        else:
            list_badman.remove(killed)
    if len(list_badman)==0 and 1 in list_goodman:
        return True
    else:
        return False


#主体程序
k=int(input())
#准备好人和坏人列表
list_goodman=[]
list_badman=[]
for i in range(1,k+1):
    list_goodman.append(i)
for i in range(k+1,2*k+1):
    list_badman.append(i)
m=1
while True:
    if josefu(2*k,m):
        print(m)
        break
    else:
        m+=1

很烦 尽管已经给出erro了但是还是不知道到底错哪了,明天再想 

搞个半天是我题目理解错了,按照我自己的题目的理解的意思就是:

#encoding=utf-8
def josefu(n,k):
    # 准备好人和坏人列表
    list_goodman = []
    list_badman = []
    for i in range(1, int(n/2 + 1)):
        list_goodman.append(i)
    for i in range(int((n/2) + 1), int(2 * (n/2) + 1)):
        list_badman.append(i)
    #n表示总人数 k表示每次杀人的间隔
    #准备一个porple列表存储n个人
    people=list(range(1,n+1))
    #current表示数到哪儿来了,值得注意的就是crrent是数组下标所以要从0开始
    current=0
    while len(list_badman)>0:
        #计算出下一个被杀的人的位置
        current=(current+k-1)%len(people)
        #根据current杀人
        killed=people.pop(current)
        if killed==1:
            return False
        if killed in list_goodman:
            list_goodman.remove(killed)
        else:
            list_badman.remove(killed)
    if len(list_badman)==0 and 1 in list_goodman:
        return True
    else:
        return False


#主体程序
k=int(input())
m=1
while True:
    if josefu(2*k,m):
        print(m)
        break
    else:
        m+=1

这个代码按照我对题目的意思就是正确的,明天再仔细看看题目到底是什么意思

题目的意思应该是:前k个被杀的都是坏人,那不就简单了。。。

#encoding=utf-8
def josefu(n,k):
    # 准备好人和坏人列表
    list_goodman = []
    list_badman = []
    for i in range(1, int(n/2 + 1)):
        list_goodman.append(i)
    for i in range(int((n/2) + 1), int(2 * (n/2) + 1)):
        list_badman.append(i)
    #n表示总人数 k表示每次杀人的间隔
    #准备一个porple列表存储n个人
    people=list(range(1,n+1))
    #current表示数到哪儿来了,值得注意的就是crrent是数组下标所以要从0开始
    current=0
    while len(list_badman)>0:
        #计算出下一个被杀的人的位置
        current=(current+k-1)%len(people)
        #根据current杀人
        killed=people.pop(current)
        if killed in list_goodman:
            return False
        else:
            list_badman.remove(killed)
    return True


#主体程序
k=int(input())
m=1
while True:
    if josefu(2*k,m):
        print(m)
        break
    else:
        m+=1

上面这段代码就是正确答案

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值