我理解的回溯法
- 回溯法本质上就是穷举法,对穷举法的优化,优化的关键在于判断哪些情况是不需要考虑的,然后不去遍历这些不必要的情况(剪枝)。
- 理解穷举法,要理解回溯法就要先真正明白穷举法。用下面例题来理解一下穷举法
输出给的数字的全排列
输入:1 2 3
输出:
[
[1, 2, 3],
[1, 3, 2],
[2, 1, 3],
[2, 3, 1],
[3, 1, 2],
[3, 2, 1]
]
核心步骤的伪代码:
Permutation(array A, array B){
If Array B is OK
Return array A
Else
For I in B:
Permutation(A add I, B remove I)
}
Python实现:
# Full Permutation全排列
def permute(numbers: list):
sorted(numbers)
visited = [0 for i in numbers]
output = []
middle = []
helper(numbers, visited, middle, output)
return output
def helper(numbers: list, visited: list, middle: list, output: list):
if len(middle) is len(numbers):
output.append(middle.copy())
return
for i in range(0, len(numbers)):
if visited[i] is 0:
visited[i] = 1
middle.append(numbers[i])
helper(numbers, visited, middle, output)
visited[i] = 0
middle.pop()
if __name__ == '__main__':
nums = [1, 2, 3]
print(permute(nums))
- N皇后问题,这个在回溯法中比较经典,我们理解了穷举法的全排列,就可以试着理解N皇后问题,其实全排列实现也是用到了回溯的思想。
我们以8皇后为例,8*8的棋盘上,放8个皇后的棋子,使他们不能在同行同列和对角线上。
输入:8
输出:92
Python实现:
# N queen n 皇后问题
def n_queens(n: int):
output = [0]
middle = [-1 for i in range(0, n)]
compute_n_queen(n, 0, middle, output)
return output[0]
def compute_n_queen(n: int, row: int, middle: list, output: list):
if n is row:
output[0] += 1
return
# 一行一行来
for column in range(0, n):
flag = 1
middle[row] = column
# 这里回溯之前放置的棋子,是否和这次放置的冲突,也就是回溯法的剪枝
for j in range(0, row):
# 因为我们是一行一行判断的,所以不用判断是否在同一行,只判断是否在同一列
# 是否在同一对角线判断即行列相减相加是否相同
if middle[row] is middle[j] or row - middle[row] is j - middle[j] or row + middle[row] is j + middle[j]:
flag = 0
break
if flag:
compute_n_queen(n, row + 1, middle, output)
if __name__ == '__main__':
print(n_queens(8))
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。