Решите проблему N-ферзей: изучение различных методов ограничения ветвей

Задача о N ферзях — это классическая головоломка, в которой нам нужно разместить N ферзей на шахматной доске NxN таким образом, чтобы никакие два ферзя не угрожали друг другу. Хотя метод грубой силы возможен, он становится непрактичным для плат большего размера. Именно здесь в игру вступают методы ограничения ветвей. В этой статье мы рассмотрим несколько методов эффективного решения проблемы N-Queens с использованием ограничения ветвей, а также приведем множество примеров кода.

Метод 1: базовый поиск с возвратом
Давайте начнем с простого алгоритма возврата для решения проблемы N-ферзей. Этот подход предполагает систематическое размещение ферзей на доске и возврат назад всякий раз, когда мы сталкиваемся с конфликтами. Вот фрагмент кода для иллюстрации:

def solve_n_queens(n):
    board = [[0] * n for _ in range(n)]
    solutions = []
    def backtrack(row):
        if row == n:
            solutions.append(board)
            return
        for col in range(n):
            if is_safe(board, row, col):
                board[row][col] = 1
                backtrack(row + 1)
                board[row][col] = 0
    def is_safe(board, row, col):
        # Check row and column
        for i in range(n):
            if board[i][col] == 1 or board[row][i] == 1:
                return False
        # Check diagonal
        for i, j in zip(range(row, -1, -1), range(col, -1, -1)):
            if board[i][j] == 1:
                return False
        for i, j in zip(range(row, -1, -1), range(col, n, 1)):
            if board[i][j] == 1:
                return False
        return True
    backtrack(0)
    return solutions

Метод 2: ограничение на основе строк
В базовом методе обратного отслеживания мы перебираем все столбцы для каждой строки. Однако мы можем повысить эффективность, используя ограничение на основе строк. Идея состоит в том, чтобы проверять только те столбцы, которые безопасны для текущей строки. Вот оптимизированная версия алгоритма возврата с использованием ограничения по строкам:

def solve_n_queens_row_based(n):
    board = [-1] * n
    solutions = []
    def backtrack(row):
        if row == n:
            solutions.append(board.copy())
            return
        for col in range(n):
            if is_safe(row, col):
                board[row] = col
                backtrack(row + 1)
                board[row] = -1
    def is_safe(row, col):
        for i in range(row):
            if board[i] == col or abs(board[i] - col) == abs(i - row):
                return False
        return True
    backtrack(0)
    return solutions

Метод 3. Ограничение на основе столбцов.
Другой подход заключается в использовании ограничения на основе столбцов. В этом методе мы перебираем все строки для каждого столбца и проверяем безопасные позиции. Вот пример реализации:

def solve_n_queens_column_based(n):
    board = [-1] * n
    solutions = []
    def backtrack(col):
        if col == n:
            solutions.append(board.copy())
            return
        for row in range(n):
            if is_safe(row, col):
                board[col] = row
                backtrack(col + 1)
                board[col] = -1
    def is_safe(row, col):
        for i in range(col):
            if board[i] == row or abs(board[i] - row) == abs(i - col):
                return False
        return True
    backtrack(0)
    return solutions

Метод 4: уменьшение симметрии
Уменьшение симметрии — это метод, который использует симметрию в задаче для уменьшения пространства поиска. Рассматривая только подмножество решений и применяя преобразования, мы можем существенно ускорить работу алгоритма. Вот пример:

def solve_n_queens_symmetry_reduction(n):
    board = [-1] * n
    solutions = []
    def backtrack(col):
        if col == n // 2:
            solutions.append(board.copy())
            return
        for row in range(n):
            if is_safe(row, col):
                board[col] = row
                backtrack(col + 1)
                board[col] = -1
    def is_safe(row, col):
        for i in range(col):
            if board[i] == row or abs(board[i] - row) == abs(i - col):
                return False
        return True
    backtrack(0)
    # Generate symmetric solutions
    for solution in solutions.copy():
        symmetric_solution = solution.copy()
        for i in range(n // 2, n):
            symmetric_solution[n - 1 - i] = solution[i]
        solutions.append(symmetric_solution)
    return solutions

В этой статье мы рассмотрели несколько методов решения проблемы N-ферзей с использованием методов ограничения ветвей. Мы начали с базового алгоритма поиска с возвратом, а затем оптимизировали его, используя ограничение на основе строк и ограничение на основе столбцов. Мы также обсудили концепцию снижения симметрии для уменьшения пространства поиска. Используя эти методы, мы можем эффективно найти решение проблемы N-ферзей даже для досок большего размера.

Помните, выбор метода зависит от конкретных требований и ограничений вашей проблемы. Поэкспериментируйте с разными подходами и посмотрите, какой из них лучше всего подходит для вашего сценария.

Итак, вперед, решайте проблему N-ферзей с помощью методов ограничения ветвей и открывайте мир эффективных решений!