Clasa a XI-a · Metoda backtrackingRead in English

Problema celor n dame în C++

În engleză: The n-queens problem

ExponențialăC++1776 de linii2 exemple

Ideea

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.

Descrierea în engleză

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.

Complexitate
exponențială; mult sub n^n datorită condițiilor de continuare
Clasa
Clasa a XI-a (Grade 11)

Exemple

Exemplul 1

Intrare

4

Ieșire așteptată

2 4 1 3
3 1 4 2
Total: 2
Exemplul 2

Intrare

3

Ieșire așteptată

Total: 0

Codul C++

Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.

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;
}

Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.