📜  Python回溯(1)

📅  最后修改于: 2023-12-03 15:19:32.403000             🧑  作者: Mango

Python回溯

Python回溯是一种常用的算法,它允许程序在搜索问题的解空间时回退到之前的状态并重试另一种可能的解决方案。回溯算法可以用于解决很多问题,例如八皇后问题、数独、迷宫、排列组合等。

回溯思想

回溯可以理解为“不断前进、不行就退后、再试其他方法”的一种思想。具体来说,回溯算法借助递归实现,在搜索问题的解空间时,每到一个节点(状态),程序搜索完毕之后,要么找到了问题的解,要么必须回溯到上一个节点继续搜索。

以下是一个典型的回溯算法框架:

def backtrack(路径, 选择列表):
    if 满足结束条件:
        记录结果
        return

    for 选择 in 选择列表:
        做选择
        backtrack(新路径, 新选择列表)
        撤销选择
八皇后问题

八皇后问题是指在一个8×8的国际象棋棋盘上放置8个皇后,使得任意两个皇后都不能在同一行、同一列或同一斜线上。回溯算法是解决八皇后问题的常见方法。以下是该问题的一种Python实现:

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        res = []
        self.dfs([-1]*n, 0, [], res)
        return res

    def dfs(self, nums, index, path, res):
        if index == len(nums):
            res.append(path)
            return

        for i in range(len(nums)):
            nums[index] = i
            if self.valid(nums, index):
                tmp = "."*len(nums)
                self.dfs(nums, index+1, path+[tmp[:i]+"Q"+tmp[i+1:]], res)

    def valid(self, nums, n):
        for i in range(n):
            if abs(nums[i]-nums[n]) == n-i or nums[i] == nums[n]:
                return False
        return True
数独问题

数独是一种数字逻辑谜题,由9个3×3的小方格组成一个大的9×9的方格,要求在每行、每列和每个小方格中分别填入数字1-9,使得每行、每列和每个小方格中的数字都不重复。以下是该问题的一种Python实现:

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        self.dfs(board, 0, 0)

    def dfs(self, board, row, col):
        if col == 9:
            return self.dfs(board, row+1, 0)
        if row == 9:
            return True
        if board[row][col] != ".":
            return self.dfs(board, row, col+1)

        for num in range(1, 10):
            if self.isValid(board, row, col, str(num)):
                board[row][col] = str(num)
                if self.dfs(board, row, col+1):
                    return True
                board[row][col] = '.'
        return False

    def isValid(self, board, row, col, num):
        for i in range(9):
            if board[row][i] == num or board[i][col] == num or board[(row//3)*3+i//3][(col//3)*3+i%3] == num:
                return False
        return True
总结

回溯算法是一种非常实用的算法,可应用于许多问题的求解。在使用回溯算法时,要注意写出正确的状态转移方程和结束条件,并避免重复计算。