Problem N-Queens z wykorzystaniem cofania w Java/C++

Wprowadzenie

Problem N Hetmanów to znane wyzwanie w dziedzinie informatyki, polegające na umieszczeniu N hetmanów na szachownicy o wymiarach N×N w taki sposób, by żaden hetman nie atakował innego. Do rozwiązania tego problemu można wykorzystać wiele metod, a jedną z najprostszych jest algorytm przeszukiwania z powrotami (backtracking).

Algorytm powrotu polega na systematycznym umieszczaniu hetmanów na planszy, a w przypadku napotkania nieprawidłowej konfiguracji – wycofywaniu się i poszukiwaniu alternatywnych ustawień. Poniżej znajduje się szczegółowy opis działania algorytmu:

Algorytm Przeszukiwania z Powrotami dla Problemu N Hetmanów

1. Inicjalizacja:
– Umieść pierwszego hetmana w pierwszym wierszu i pierwszej kolumnie szachownicy.

2. Generowanie Konfiguracji:
– Gdy obecna konfiguracja jest bezpieczna (żaden hetman nie atakuje innego), przejdź do kolejnego wiersza i ustaw hetmana w pierwszej kolumnie.
– Jeśli obecna konfiguracja jest zagrożona, spróbuj przesunąć hetmana do następnej kolumny w tym samym wierszu.

3. Cofanie:
– Jeśli nie da się umieścić hetmana w żadnej kolumnie bieżącego wiersza, cofnij się, usuwając hetmana z poprzedniego wiersza i spróbuj umieścić go w kolejnej kolumnie.

4. Iteracja:
– Powtarzaj kroki 2-3, aż wszystkie hetmany zostaną umieszczone lub do wyczerpania wszystkich możliwych konfiguracji.

Implementacja w Języku Java

Poniższy kod prezentuje implementację algorytmu w języku Java:


import java.util.ArrayList;
import java.util.List;

public class NQueensBacktracking {

    public static void main(String[] args) {
        int n = 8;
        List<List<Integer>> solutions = solveNQueens(n);
        for (List<Integer> solution : solutions) {
            System.out.println(solution);
        }
    }

    public static List<List<Integer>> solveNQueens(int n) {
        List<List<Integer>> solutions = new ArrayList<>();
        int[] board = new int[n];
        solveNQueens(board, 0, solutions);
        return solutions;
    }

    private static void solveNQueens(int[] board, int row, List<List<Integer>> solutions) {
        if (row == board.length) {
            List<Integer> solution = new ArrayList<>();
            for (int i = 0; i < board.length; i++) {
                solution.add(board[i]);
            }
            solutions.add(solution);
            return;
        }

        for (int col = 0; col < board.length; col++) {
            if (isSafe(board, row, col)) {
                board[row] = col;
                solveNQueens(board, row + 1, solutions);
                board[row] = 0;
            }
        }
    }

    private static boolean isSafe(int[] board, int row, int col) {
        for (int i = 0; i < row; i++) {
            if (board[i] == col || Math.abs(board[i] - col) == row - i) {
                return false;
            }
        }
        return true;
    }
}

Implementacja w Języku C++

Poniższy kod przedstawia implementację algorytmu w języku C++:


#include <iostream>
#include <vector>

using namespace std;

bool isSafe(int board[][N], int row, int col) {
  for (int i = 0; i < row; i++) {
    if (board[i][col] || abs(board[i][col] - col) == row - i) {
      return false;
    }
  }
  return true;
}

void solveNQueens(int board[][N], int row, vector<vector<int>> &solutions) {
  if (row == N) {
    vector<int> solution(N);
    for (int i = 0; i < N; i++) {
      solution[i] = board[i][i];
    }
    solutions.push_back(solution);
    return;
  }

  for (int col = 0; col < N; col++) {
    if (isSafe(board, row, col)) {
      board[row][col] = 1;
      solveNQueens(board, row + 1, solutions);
      board[row][col] = 0;
    }
  }
}

vector<vector<int>> solveNQueens(int n) {
  vector<vector<int>> solutions;
  int board[N][N] = {0};
  solveNQueens(board, 0, solutions);
  return solutions;
}

int main() {
  int n = 8;
  vector<vector<int>> solutions = solveNQueens(n);
  for (vector<int> solution : solutions) {
    for (int i = 0; i < n; i++) {
      cout << solution[i] << " ";
    }
    cout << endl;
  }
  return 0;
}

Podsumowanie

Algorytm powrotu stanowi prosty i efektywny sposób rozwiązania problemu N Hetmanów. Jego złożoność czasowa wynosi O(n^n), gdzie n to liczba hetmanów. Metodę tę można adaptować do rozwiązywania innych zagadnień związanych z rozmieszczaniem elementów.

Pomimo swojej prostoty, algorytm powrotu może być czasochłonny dla większych wartości n. W takich przypadkach bardziej wydajne mogą okazać się inne algorytmy, takie jak rekurencja z ograniczeniami.

Najczęściej Zadawane Pytania (FAQ)

1. Na czym polega problem N Hetmanów?
Problem polega na umieszczeniu N hetmanów na szachownicy N×N w taki sposób, by żaden hetman nie mógł zaatakować innego.

2. Czym jest algorytm przeszukiwania z powrotami?
To algorytm, który systematycznie próbuje różne opcje, a w przypadku niepowodzenia wraca do poprzedniego stanu i podejmuje kolejną próbę.

3. Jak zaimplementować algorytm powrotu dla problemu N Hetmanów?
Najpierw umieszczamy hetmana na szachownicy, a następnie iterujemy przez różne ustawienia, cofając się, jeśli aktualne ustawienie jest błędne.

4. Jaka jest złożoność czasowa algorytmu powrotu?
Złożoność wynosi O(n^n), gdzie n to liczba hetmanów.

5. Czy istnieją alternatywne algorytmy rozwiązania problemu N Hetmanów?
Tak, można zastosować np. rekurencję z ograniczeniami, która może okazać się bardziej efektywna dla dużych wartości n.

6. Jaki jest cel rozwiązywania problemu N Hetmanów?
To zadanie jest doskonałym ćwiczeniem w projektowaniu algorytmów i pomaga zrozumieć ich złożoność.

7. Czy problem N Hetmanów znajduje zastosowanie w praktyce?
Tak, ma zastosowania w planowaniu, optymalizacji i sztucznej inteligencji.

8. Czy można wykorzystać uczenie maszynowe do rozwiązania problemu N Hetmanów?
Tak, ale jest to rozwiązanie bardziej złożone i mniej efektywne niż metody tradycyjne.

9. Czy problem N Hetmanów jest odpowiedni dla początkujących programistów?
Tak, jest to dobre wprowadzenie do algorytmiki, ale może być wyzwaniem przy większych wartościach n.

10. Gdzie mogę znaleźć więcej informacji o problemie N Hetmanów?
Wikipedia
GeeksforGeeks


newsblog.pl