我理解的回溯法

  1. 回溯法本质上就是穷举法,对穷举法的优化,优化的关键在于判断哪些情况是不需要考虑的,然后不去遍历这些不必要的情况(剪枝)。
  2. 理解穷举法,要理解回溯法就要先真正明白穷举法。用下面例题来理解一下穷举法

输出给的数字的全排列

输入: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 outputdef 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))
  1. 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))