数据结构与算法之 leetcode 回溯算法棋盘 N 皇后 / 数独求解

数据结构与算法阿木 发布于 5 天前 4 次阅读


摘要:

回溯算法是一种在解决组合问题时非常有效的算法。它通过递归尝试所有可能的解,并在遇到不满足条件的情况时回溯到上一个状态,从而找到问题的解。本文将以N皇后问题和数独求解为例,深入探讨回溯算法在棋盘问题中的应用,并展示相应的代码实现。

一、

棋盘问题是计算机科学中经典的算法问题,其中N皇后问题和数独求解是最具代表性的两个问题。这两个问题都可以通过回溯算法来解决。本文将首先介绍回溯算法的基本原理,然后分别针对N皇后问题和数独求解进行详细的分析和代码实现。

二、回溯算法原理

回溯算法的基本思想是:从问题的解空间中寻找一个解,如果这个解不满足条件,则回溯到上一个状态,尝试其他的可能性。这个过程可以递归地进行,直到找到满足条件的解或者所有可能性都被尝试过。

回溯算法通常包含以下步骤:

1. 选择一个候选解;

2. 尝试将候选解应用到当前状态;

3. 如果当前状态满足条件,则继续尝试下一个候选解;

4. 如果当前状态不满足条件,则回溯到上一个状态,尝试其他的候选解;

5. 重复步骤2-4,直到找到满足条件的解或者所有可能性都被尝试过。

三、N皇后问题

N皇后问题是指在一个N×N的棋盘上放置N个皇后,使得它们互不攻击。以下是N皇后问题的回溯算法实现:

python

def is_valid(board, row, col):


for i in range(row):


if board[i] == col or


board[i] - i == col - row or


board[i] + i == col + row:


return False


return True

def solve_n_queens(board, row):


if row == len(board):


return True


for col in range(len(board)):


if is_valid(board, row, col):


board[row] = col


if solve_n_queens(board, row + 1):


return True


board[row] = -1


return False

def print_board(board):


for row in board:


print(' '.join('Q' if x == row else '.' for x in range(len(board))))

def solve_n_queens_util(n):


board = [-1] n


if not solve_n_queens(board, 0):


print("Solution does not exist")


else:


print_board(board)

Example usage:


n = 8


solve_n_queens_util(n)


四、数独求解

数独求解问题是指在一个9×9的棋盘上填入数字,使得每一行、每一列以及每一个3×3的小格子内的数字都不重复。以下是数独求解的回溯算法实现:

python

def is_valid(board, row, col, num):


for x in range(9):


if board[row][x] == num or board[x][col] == num:


return False


start_row, start_col = 3 (row // 3), 3 (col // 3)


for i in range(3):


for j in range(3):


if board[i + start_row][j + start_col] == num:


return False


return True

def solve_sudoku(board):


empty = find_empty_location(board)


if not empty:


return True


row, col = empty


for num in range(1, 10):


if is_valid(board, row, col, num):


board[row][col] = num


if solve_sudoku(board):


return True


board[row][col] = 0


return False

def find_empty_location(board):


for i in range(9):


for j in range(9):


if board[i][j] == 0:


return (i, j)


return None

def print_board(board):


for row in board:


print(' '.join(str(num) if num != 0 else '.' for num in row))

Example usage:


board = [


[5, 3, 0, 0, 7, 0, 0, 0, 0],


[6, 0, 0, 1, 9, 5, 0, 0, 0],


[0, 9, 8, 0, 0, 0, 0, 6, 0],


[8, 0, 0, 0, 6, 0, 0, 0, 3],


[4, 0, 0, 8, 0, 3, 0, 0, 1],


[7, 0, 0, 0, 2, 0, 0, 0, 6],


[0, 6, 0, 0, 0, 0, 2, 8, 0],


[0, 0, 0, 4, 1, 9, 0, 0, 5],


[0, 0, 0, 0, 8, 0, 0, 7, 9]


]

if solve_sudoku(board):


print_board(board)


else:


print("No solution exists")


五、总结

本文通过N皇后问题和数独求解的实例,详细介绍了回溯算法在棋盘问题中的应用。回溯算法是一种强大的工具,可以解决许多组合问题。通过理解回溯算法的原理和实现,我们可以更好地解决实际问题,提高编程能力。