回溯法:全排列
阿新 • • 發佈:2018-12-17
全排列
遞迴實現:把元素換到陣列首位,剩下的部分做全排列
def constraint():
return True
def bound():
return True
def perm_backtracking(depth,lst):
size = len(lst)
if depth == size:
print(lst)
else:
for i in range(depth,size):
if constraint() and bound():
lst[depth],lst[i] = lst[i],lst[depth]
perm_backtracking(depth+1,lst)
lst[depth],lst[i] = lst[i],lst[depth]
迭代實現,可以參考完全n叉樹,這個應該是一個通用的迭代的處理方法,在這裡:只要不在同一列就行了
def perm_backtracking_iteration(depth,lst):
size = len(lst)
Selected =[-1]*size
# 排列數,列號不能重複
def place(k):
for i in range(k):
if Selected[i] == Selected[k]:
return False
return True
while depth >=0:
Selected[depth] +=1
# 直到選擇一個可行的解
while Selected[depth]<size and not place(depth):
Selected[ depth] +=1
# 這個就是回溯條件,子集樹不為空
if Selected[depth] <= size-1:
if depth == size-1:
# print Selected
# 解碼結果,Selected裡面對應的是選擇了哪一個數
for i in Selected:
print lst[i],
print ""
else:
# 到達下一層時,初始化下一層的子樹的範圍
depth +=1
Selected[depth] =-1
# 回溯,還是從上一層的未選的的地方走
else:
depth -=1
A = ['A','B','C','D']
perm_backtracking(0,A)
['A', 'B', 'C', 'D']
['A', 'B', 'D', 'C']
['A', 'C', 'B', 'D']
['A', 'C', 'D', 'B']
['A', 'D', 'C', 'B']
['A', 'D', 'B', 'C']
['B', 'A', 'C', 'D']
['B', 'A', 'D', 'C']
['B', 'C', 'A', 'D']
['B', 'C', 'D', 'A']
['B', 'D', 'C', 'A']
['B', 'D', 'A', 'C']
['C', 'B', 'A', 'D']
['C', 'B', 'D', 'A']
['C', 'A', 'B', 'D']
['C', 'A', 'D', 'B']
['C', 'D', 'A', 'B']
['C', 'D', 'B', 'A']
['D', 'B', 'C', 'A']
['D', 'B', 'A', 'C']
['D', 'C', 'B', 'A']
['D', 'C', 'A', 'B']
['D', 'A', 'C', 'B']
['D', 'A', 'B', 'C']
還可以基於排列樹的迭代方式:
def perm_backtracking_iteration2(depth,lst):
size = len(lst)
Selected =[i for i in range(size)]
change = [-1]*size
count = 0
while depth >=0:
# range(Selected[depth],size)記錄的是剩餘的次數,這裡面還不能表現到底是那幾次?估計還可以改進
if Selected[depth] < size:
for i in range(Selected[depth],size):
# 交換且記錄交換
lst[depth],lst[i] = lst[i],lst[depth]
change[depth] = i
Selected[depth] +=1
if depth == size-1:
count +=1
print lst
print count
else:
depth +=1
Selected[depth] = depth
break
else:
# 子集樹為空了,回溯到上一層,在最底部是沒有交換動作的,因為change[depth]就是本身,
# 所以需要先-1,再交換,可以自己先除錯一遍
depth -=1
lst[depth],lst[change[depth]] = lst[change[depth]],lst[depth]
change[depth] = -1
A = ['A','B','C','D']
#perm_backtracking(0,A)
perm_backtracking_iteration2(0,A)
['A', 'B', 'C', 'D']
1
['A', 'B', 'D', 'C']
2
['A', 'C', 'B', 'D']
3
['A', 'C', 'D', 'B']
4
['A', 'D', 'C', 'B']
5
['A', 'D', 'B', 'C']
6
['B', 'A', 'C', 'D']
7
['B', 'A', 'D', 'C']
8
['B', 'C', 'A', 'D']
9
['B', 'C', 'D', 'A']
10
['B', 'D', 'C', 'A']
11
['B', 'D', 'A', 'C']
12
['C', 'B', 'A', 'D']
13
['C', 'B', 'D', 'A']
14
['C', 'A', 'B', 'D']
15
['C', 'A', 'D', 'B']
16
['C', 'D', 'A', 'B']
17
['C', 'D', 'B', 'A']
18
['D', 'B', 'C', 'A']
19
['D', 'B', 'A', 'C']
20
['D', 'C', 'B', 'A']
21
['D', 'C', 'A', 'B']
22
['D', 'A', 'C', 'B']
23
['D', 'A', 'B', 'C']
24