简体   繁体   English

Python回溯算法

[英]Backtracking algorithm with Python

I am trying to implement an algorithm that takes in two ints n and k where n is the number of seats in a row, and k is the number of students trying to sit in that row. 我正在尝试实现一个接受两个整数n和k的算法,其中n是一行中的座位数,k是试图坐在该行中的学生数。 The thing is that each student must be at least two seats from each other on both side. 问题是,每个学生在双方之间必须至少有两个席位。 What I have is a function that generates all subsets (an array of either 0 or 1 s, 1 meaning someone is sitting there) and I send this to a function to check to see if it is a valid subset. 我所拥有的是一个生成所有子集的函数(0或1 s的数组,1表示有人坐在那里),然后将其发送给函数以检查其是否为有效子集。 This is the code I have for that function 这是我该功能的代码

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

The code works for small inputs of k and n but if I get higher values I get an index out of list error for some reason I can't figure out. 该代码适用于k和n的较小输入,但是如果我得到更高的值,由于某种原因我将无法弄清索引错误。
Any help out be great thanks. 任何帮助都非常感谢。

O the input a is the list that looks something like this O输入a是看起来像这样的列表

['1','0','0','1','0'] # a valid subset for n=5 and k=2
['0','0','0','1','1'] # an invalid subset

EDIT: 编辑:

Code that calls process: 调用过程的代码:

'''
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()

The error I get if I use these numbers are 如果使用这些数字,我得到的错误是

if( (a[i-2] == '0') and (a[i-1] == '0') and (a[i+1] == '0') ):
IndexError: list index out of range

The indexes for an array of length n is from 0 to n-1 . 长度为n的数组的索引为0n-1 Thus accessing n is out of list. 因此,访问n不在列表中。

The code that generates the lists must have a bug if you haven't noticed this on smaller values. 如果您在较小的值上没有注意到此问题,则生成列表的代码必须存在一个错误。

It is sufficient to exclude invalid seating arrangements, namely, when the students seat next to each other ['1', '1'] or when there is only one seat between them ['1', '0', '1'] all other arrangements that have correct numbers of '1' , and '0' are valid, example : 排除无效的座位安排就足够了,即,当学生坐在彼此旁边['1', '1']或当他们之间只有一个座位时['1', '0', '1']所有其他具有正确数字'1''0'均有效, 例如

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']))

There are more efficient algorithms to generate valid subsets without checking all subsets eg, 有更有效的算法可生成有效子集,而无需检查所有子集,例如

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

n, k = 5, 2
for s in subsets(n, k):
    assert isvalid(s, n, k)
    print(s)

Output 产量

10010
10001
01001

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM