N-Queens-problem med backtracking i Java/C++

By rik


N-drottningsproblemet med återspårning i Java och C++

Introduktion

N-drottningsproblemet är ett välkänt logiskt pussel. Utmaningen består i att arrangera N damer på ett schackbräde med dimensionerna N×N, så att ingen dam kan hota en annan. En dam utgör ett hot mot en annan om de delar samma rad, kolumn eller diagonal.

För att lösa detta problem kan man använda sig av återspårning, en rekursiv algoritm som utforskar samtliga möjliga kombinationer av damplaceringar. Om algoritmen stöter på en ogiltig placering, backar den tillbaka och testar andra alternativ. Återspårning är en kraftfull men ibland långsam metod, speciellt när det handlar om stora värden på N.

Denna artikel kommer att förklara hur N-drottningsproblemet kan lösas med återspårning i både Java och C++. Vi kommer att behandla den grundläggande återspårningsalgoritmen och dessutom olika optimeringstekniker för att förbättra effektiviteten.

Java-implementering

Grundläggande algoritm för återspårning

      
public class NQueens {

    private int[] queens;
    private boolean[] cols, diag1, diag2;

    public NQueens(int n) {
        queens = new int[n];
        cols = new boolean[n];
        diag1 = new boolean[2 * n - 1];
        diag2 = new boolean[2 * n - 1];
    }

    public boolean solve() {
        return solve(0);
    }

    private boolean solve(int row) {
        if (row == queens.length) {
            return true;
        }

        for (int col = 0; col < queens.length; col++) {
            if (!cols[col] && !diag1[row + col] && !diag2[row - col + queens.length - 1]) {
                queens[row] = col;
                cols[col] = true;
                diag1[row + col] = true;
                diag2[row - col + queens.length - 1] = true;

                if (solve(row + 1)) {
                    return true;
                }

                queens[row] = 0;
                cols[col] = false;
                diag1[row + col] = false;
                diag2[row - col + queens.length - 1] = false;
            }
        }

        return false;
    }
}
      
      

Förbättrade metoder

  • Kolumnoptimering: Genom att registrera om en kolumn redan har en dam placerad, kan onödiga kontroller undvikas.
  • Diagonaloptimering: Att spåra om en diagonal är upptagen av en dam leder till färre misslyckade placeringar.
  • Beskärning: Om en placering är uppenbart felaktig, backa omedelbart istället för att fortsätta.
  • Heuristik: Välj den kolumn som leder till minst antal hot, för att hitta en lösning snabbare.

C++-implementering

Grundläggande algoritm för återspårning

    
#include <iostream>
#include <vector>

using namespace std;

class NQueens {
private:
    vector<int> queens;
    vector<bool> cols, diag1, diag2;

public:
    NQueens(int n) {
        queens.resize(n);
        cols.resize(n, false);
        diag1.resize(2 * n - 1, false);
        diag2.resize(2 * n - 1, false);
    }

    bool solve() {
        return solve(0);
    }

private:
    bool solve(int row) {
        if (row == queens.size()) {
            return true;
        }

        for (int col = 0; col < queens.size(); col++) {
            if (!cols[col] && !diag1[row + col] && !diag2[row - col + queens.size() - 1]) {
                queens[row] = col;
                cols[col] = true;
                diag1[row + col] = true;
                diag2[row - col + queens.size() - 1] = true;

                if (solve(row + 1)) {
                    return true;
                }

                queens[row] = 0;
                cols[col] = false;
                diag1[row + col] = false;
                diag2[row - col + queens.size() - 1] = false;
            }
        }

        return false;
    }
};
    
    

Förbättrade metoder

  • Kolumnoptimering: Motsvarar den Java-baserade optimeringen.
  • Diagonaloptimering: Motsvarar den Java-baserade optimeringen.
  • Beskärning: Motsvarar den Java-baserade optimeringen.
  • Heuristik: Motsvarar den Java-baserade optimeringen.

Sammanfattning

N-drottningsproblemet är ett bra exempel på hur återspårning kan användas för att hantera kombinatoriska optimeringsproblem. Implementeringarna i Java och C++ som visas ovan ger både grundläggande och förbättrade lösningar.

Genom att använda optimerade tekniker kan prestandan ökas betydligt, framförallt för stora värden på N. Heuristiken är speciellt användbar för att minska antalet steg som krävs av återspårningsalgoritmen.

N-drottningsproblemet har tillämpats inom många olika områden, såsom schack, artificiell intelligens och kryptering. Det är ett mångsidigt och utmanande problem som fortsätter att engagera programmerare och forskare.

Vanliga frågor

1. Vad är N-drottningsproblemet?
Det handlar om att placera N damer på ett N×N schackbräde så att ingen dam hotar en annan.

2. Hur löses N-drottningsproblemet?
Återspårning är en vanlig algoritm för att lösa det här problemet.

3. Hur kan återspårningsalgoritmen göras mer effektiv?
Effektiviteten kan förbättras genom tekniker som kolumn- och diagonaloptimering, beskärning och heuristik.

4. Vad menas med heuristik?
Heuristik är en strategi som används för att guida återspårningsalgoritmen mot en snabbare lösning.

5. Vilka områden tillämpas N-drottningsproblemet?
Det används inom schack, artificiell intelligens och kryptering.

6. Kan N-drottningsproblemet lösas med andra algoritmer än återspårning?
Ja, det finns alternativa metoder som genetiska algoritmer och simulerad härdning.

7. Vad är det största värdet på N som kan lösas på ett effektivt sätt?
Det beror på algoritmen som används och datorns prestanda. Med hjälp av optimering kan N-värden på flera tusen lösas inom en rimlig tidsram.

8. Finns det något onlineverktyg för att lösa N-drottningsproblemet?
Ja, det finns åtskilliga onlineverktyg som kan lösa problemet för ett visst N-värde.