Clasa a XI-a · Metoda backtrackingRead in English

Colorarea hărților în C++

În engleză: Map coloring

ExponențialăC++1782 de linii1 exemplu

Ideea

O hartă are n țări numerotate de la 1, iar m perechi (a, b) spun că țările a și b sunt vecine. Colorăm fiecare țară cu una dintre culorile 1..4 astfel încât două țări vecine să aibă culori diferite. x[k] este culoarea țării k; ea e validă dacă diferă de culorile vecinilor deja colorați (cei cu indice mai mic). Se afișează prima colorare găsită (cea mai mică lexicografic).

Descrierea în engleză

A map has n countries numbered from 1, and m pairs (a, b) say that countries a and b are neighbours. We color every country with one of the colors 1..4 so that two neighbouring countries have different colors. x[k] is the color of country k; it is valid if it differs from the colors of the neighbours already colored (those with a smaller index). The first coloring found (the lexicographically smallest) is printed.

Complexitate
O(4^n · n) în cel mai rău caz, de obicei mult mai puțin
Clasa
Clasa a XI-a (Grade 11)

Exemple

Exemplul 1

Intrare

5 7
1 2
1 3
2 3
2 4
3 4
4 5
3 5

Ieșire așteptată

1 2 3 1 2

Codul C++

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

colorarea-hartilor.cpp
/*
 * Titlu: Colorarea hărților
 * Clasa: 11
 * Capitol: Metoda backtracking
 * Descriere: O hartă are n țări numerotate de la 1, iar m perechi (a, b) spun că țările
 *            a și b sunt vecine. Colorăm fiecare țară cu una dintre culorile 1..4 astfel
 *            încât două țări vecine să aibă culori diferite. x[k] este culoarea țării k;
 *            ea e validă dacă diferă de culorile vecinilor deja colorați (cei cu indice
 *            mai mic). Se afișează prima colorare găsită (cea mai mică lexicografic).
 * Complexitate: O(4^n · n) în cel mai rău caz, de obicei mult mai puțin
 *
 * Exemplu
 * Intrare:
 * 5 7
 * 1 2
 * 1 3
 * 2 3
 * 2 4
 * 3 4
 * 4 5
 * 3 5
 * Ieșire: 1 2 3 1 2
 */
#include <iostream>
using namespace std;

int n, m, x[50];
bool vecin[50][50], gasit = false;

bool valid(int k)
{
    for (int i = 1; i < k; i++)
    {
        if (vecin[i][k] && x[i] == x[k])
        {
            return false;
        }
    }
    return true;
}

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

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        vecin[a][b] = vecin[b][a] = true;
    }
    back(1);
    if (!gasit)
    {
        cout << "Nu exista colorare cu 4 culori\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.