[英]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
的数组的索引为0
到n-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
n, k = 5, 2
for s in subsets(n, k):
assert isvalid(s, n, k)
print(s)
10010
10001
01001
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.