1. 程式人生 > >回溯法:全排列

回溯法:全排列

全排列

遞迴實現:把元素換到陣列首位,剩下的部分做全排列

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