[英]Backtracking algorithm with Python
我正在嘗試實現一個接受兩個整數n和k的算法,其中n是一行中的座位數,k是試圖坐在該行中的學生數。 問題是,每個學生在雙方之間必須至少有兩個席位。 我所擁有的是一個生成所有子集的函數(0或1 s的數組,1表示有人坐在那里),然后將其發送給函數以檢查其是否為有效子集。 這是我該功能的代碼
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是看起來像這樣的列表
['1','0','0','1','0'] # a valid subset for n=5 and k=2
['0','0','0','1','1'] # an invalid subset
編輯:
調用過程的代碼:
'''
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()
如果使用這些數字,我得到的錯誤是
if( (a[i-2] == '0') and (a[i-1] == '0') and (a[i+1] == '0') ):
IndexError: list index out of range
長度為n
的數組的索引為0
到n-1
。 因此,訪問n
不在列表中。
如果您在較小的值上沒有注意到此問題,則生成列表的代碼必須存在一個錯誤。
排除無效的座位安排就足夠了,即,當學生坐在彼此旁邊['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']))
有更有效的算法可生成有效子集,而無需檢查所有子集,例如
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.