Grade 11 · BacktrackingCitește în română

The n-queens problem

Original: Problema celor n dame

ExponentialC++1776 lines2 examples

The idea

We place n queens on an n × n board so that none attacks another (no pair on the same row, column or diagonal). We put one queen on every row, and x[k] is the column of the queen on row k. Queen k is valid if for every row i < k: x[i] ≠ x[k] (a different column) and |x[i] - x[k]| ≠ k - i (a different diagonal). All solutions and their number are printed.

Original description (Romanian)

Așezăm n dame pe o tablă n × n astfel încât să nu se atace (nicio pereche pe aceeași linie, coloană sau diagonală). Punem câte o damă pe fiecare linie, iar x[k] este coloana damei de pe linia k. Dama k e validă dacă pentru orice linie i < k: x[i] ≠ x[k] (altă coloană) și |x[i] - x[k]| ≠ k - i (altă diagonală). Se afișează toate soluțiile și numărul lor.

Complexity
exponential; far below n^n thanks to the continuation conditions
Grade
Grade 11 (Clasa a XI-a)

Examples

Example 1

Input

4

Expected output

2 4 1 3
3 1 4 2
Total: 2
Example 2

Input

3

Expected output

Total: 0

The code

Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.

n-dame.cpp
/*
 * Titlu: Problema celor n dame
 * Clasa: 11
 * Capitol: Metoda backtracking
 * Descriere: Așezăm n dame pe o tablă n × n astfel încât să nu se atace (nicio pereche
 *            pe aceeași linie, coloană sau diagonală). Punem câte o damă pe fiecare linie,
 *            iar x[k] este coloana damei de pe linia k. Dama k e validă dacă pentru orice
 *            linie i < k: x[i] ≠ x[k] (altă coloană) și |x[i] - x[k]| ≠ k - i (altă
 *            diagonală). Se afișează toate soluțiile și numărul lor.
 * Complexitate: exponențială; mult sub n^n datorită condițiilor de continuare
 *
 * Exemplu
 * Intrare: 4
 * Ieșire:
 * 2 4 1 3
 * 3 1 4 2
 * Total: 2
 *
 * Exemplu
 * Intrare: 3
 * Ieșire: Total: 0
 */
#include <iostream>
using namespace std;

int n, x[20], total = 0;

bool valid(int k)
{
    for (int i = 1; i < k; i++)
    {
        int dif = x[i] - x[k];
        if (dif < 0)
        {
            dif = -dif;
        }
        if (dif == 0 || dif == k - i)
        {
            return false;
        }
    }
    return true;
}

void back(int k)
{
    for (int c = 1; c <= n; c++)
    {
        x[k] = c;
        if (valid(k))
        {
            if (k == n)
            {
                total++;
                for (int i = 1; i <= n; i++)
                {
                    cout << x[i] << ' ';
                }
                cout << '\n';
            }
            else
            {
                back(k + 1);
            }
        }
    }
}

int main()
{
    cin >> n;
    back(1);
    cout << "Total: " << total << '\n';
    return 0;
}

Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.