首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Python实现回溯算法

用Python实现回溯算法
EN

Stack Overflow用户
提问于 2012-02-17 14:39:00
回答 2查看 7K关注 0票数 2

我正在尝试实现一个算法,它接受两个整数n和k,其中n是一行中的座位数,k是试图坐在一行中的学生的数量。问题是,每个学生必须在两侧至少有两个座位。我拥有的是一个生成所有子集的函数(一个由0或1组成的数组,1表示有人坐在那里),然后我将其发送到一个函数,以检查它是否是有效的子集。这是我为该函数编写的代码

代码语言:javascript
复制
def process(a,num,n):
    c = a.count('1')
    #If the number of students sitting down (1s) is equal to the number k, check the subset
    if(c == num):
        printa = True
        for i in range(0,n):
            if(a[i] == '1'):
                if(i == 0):
                    if( (a[i+1] == '0') and (a[i+2] == '0') ):
                        break
                    else:
                        printa = False
                elif(i == 1):
                    if( (a[i-1] == '0') and (a[i+1] == '0') and (a[i+2] == '0') ):
                        break
                    else:
                        printa = False
                elif(i == (n-1)):
                    if( (a[i-2] == '0') and (a[i-1] == '0') and (a[i+1] == '0') ):
                        break
                    else:
                        printa = False
                elif(i == n):
                    if( (a[i-2] == '0') and (a[i-1] == '0') ):
                        break
                else:
                    printa = False                    
            else:
                if( (a[i-2] == '0') and (a[i-1] == '0') and (a[i+1] == '0') and (a[i+2] == '0') ):
                    break
                else:
                    printa = False
        if(printa):
            print a
    else:
        return

这段代码适用于k和n的小输入,但是如果我得到更高的值,我会得到一个列表错误的索引,因为某些原因,我不能确定。

任何帮助都是非常感谢的。

O输入a是如下所示的列表

代码语言:javascript
复制
['1','0','0','1','0'] # a valid subset for n=5 and k=2
['0','0','0','1','1'] # an invalid subset

编辑:

调用进程的代码:

代码语言:javascript
复制
'''
This function will recursivly call itself until it gets down to the leaves then sends that
subset to process function.  It appends
either a 0 or 1 then calls itself
'''
def seatrec(arr,i,n,k):
    if(i==n):
        process(arr,k,n)
        return
    else:
        arr.append("0")
        seatrec(arr,i+1,n,k)
        arr.pop()
        arr.append("1")
        seatrec(arr,i+1,n,k)
        arr.pop()
    return
'''
This is the starter function that sets up the recursive calls
'''
def seat(n,k):
    q=[]
    seat(q,0,n,k)

def main():
    n=7
    k=3
    seat(n,k)

if __name__ == "__main__":
    main()

如果我使用这些数字,我得到的错误是

代码语言:javascript
复制
if( (a[i-2] == '0') and (a[i-1] == '0') and (a[i+1] == '0') ):
IndexError: list index out of range
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-17 15:45:35

排除无效的座位安排就足够了,即当学生彼此相邻时,或者当他们之间只有一个座位时,所有其他具有正确数量的['1', '1']['1', '0', '1'] '1''0'是有效的,example

代码语言:javascript
复制
def isvalid(a, n, k):
    if not isinstance(a, basestring):
       a = ''.join(a) # `a` is a list of '1', '0'
    return (len(a) == n and a.count('1') == k and a.count('0') == (n-k) and
            all(p not in a for p in ['11', '101']))

存在在不检查所有子集的情况下生成有效子集的更有效的算法,

代码语言:javascript
复制
def subsets(n, k):
    assert k >= 0 and n >= 0
    if k == 0: # no students, all seats are empty
        yield '0'*n
    elif k == 1 and (n == 1 or n == 2): # the last student at the end of the row
        yield '1' + '0'*(n-1) # either '1' or '10'
        if n == 2: yield '01'
    elif n > 3*(k-1): # there are enough empty seats left for k students
        for s in subsets(n-3, k-1):
            yield '100' + s # place a student
        for s in subsets(n-1, k):
            yield '0' + s   # add empty seat

Example

代码语言:javascript
复制
n, k = 5, 2
for s in subsets(n, k):
    assert isvalid(s, n, k)
    print(s)

输出

代码语言:javascript
复制
10010
10001
01001
票数 3
EN

Stack Overflow用户

发布于 2012-02-17 14:46:23

长度为n的数组的索引是从0n-1。因此,访问n不在列表中。

如果你没有注意到在较小的值上,生成列表的代码一定有一个bug。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9323966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档