Задача про вісім ферзів

Задача про вісім ферзів полягає в такому розміщенні восьми ферзів на шахівниці, що жодна з них не ставить під удар один одного. Тобто, вони не повинні стояти в одній вертикалі, горизонталі чи діагоналі. Задача про вісім ферзів є прикладом загальної задачі про n ферзів: задачі розміщення n ферзів на шахівниці розміром n × n, яка має розв'язки для n = 1 або n  4.

abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Один з розв'язків задачі про вісім ферзів.

Задача має 92 розв'язки. Якщо відкинути схожі композиції з точністю до відбиття (віддзеркалення позиції на шахівниці) та обертання (обертання позиції на шахівниці), залишиться 12 унікальних розв'язків.

Історія

Задачу показав у 1848 р. шахіст Макс Бецель (нім. Max Friedrich William Bezzel), і вже через три роки математики, зокрема, Карл Гаус, працювали над пошуком її розв'язків та узагальненого варіанту. Перші розв'язки були знайдені Францом Науком (Franz Nauck) 1850 р. Також Наук запропонував розширити задачу до n ферзів (на шахівниці розміром n × n). 1874 р. Ґюнтер (S. Günther) запропонував метод пошуку розв'язків із використанням визначників, а Джеймс Глейшер (англ. James Whitbread Lee Glaisher) його вдосконалив.

Едсгер Дейкстра використав цю задачу 1972 р. аби показати можливості того, що він назвав структурним програмуванням. Він надрукував докладне описання розробки алгоритму пошуку в глибину з поверненням[1].

Алгоритми пошуку розв'язків

Рекурсивний алгоритм з поверненням

Приклад роботи рекурсивного алгоритму з поверненням.

Задача про ферзів є прикладом простої, але не тривіальної задачі, яку можна розв'язати із допомогою рекурсивного алгоритму, оскільки задача з n ферзями може бути представлена як задача розміщення ферзя для розв'язку з n  1 ферзями. Нарешті, задачу можна звести до задачі з 8 ферзями, розв'язком якої є порожня шахівниця.

Наступна програма мовою Python знаходить всі розв'язки для задачі з n ферзями використовуючи рекурсивний алгоритм. Він рекурсивно досліджує шахівниці розміром n × n, n × n  1, n × n  2, …

В програмі враховано те, що ферзі не можуть стояти на одному рядку.

Також враховано те, що розв'язок з n  1 ферзями на шахівниці n × n  1 містить в собі розв'язок задачі з n  2 ферзями на шахівниці розміром n × n  2.

Тобто, алгоритм також отримує всі розв'язки, які входять до знайденого розв'язку на менших шахівницях.

Для шахівниці 8×8 програма переглядає 15 720 позицій.

def queenproblem(rows, cols):
    if rows <= 0:
        return [[]] # порожня дошка є розв'язком для випадку без ферзів
    else:
        return add_queen(rows - 1, cols, queenproblem(rows - 1, cols))

# Переглянути всі комбінації для часткового розв'язку,
# для яких можна додати ферзя в «new_row».
# Якщо відсутні конфлікти з частковим розв'язком,
# тоді знайдено новий розв'язок для додаткового рядка.
def add_queen(new_row, cols, known_solutions):
    new_solutions = []
    for solution in known_solutions:
        # спробувати розмістити ферзя в кожну комірку додаткового рядка
        for new_column in range(cols):
            # print('Спроба: %s в рядку %s' % (new_column, new_row))
            if no_conflict(new_row, new_column, solution):
                # відсутні конфлікти, цей варіант є розв'язком
                new_solutions.append(solution + [new_column])
    return new_solutions

# Перевіряє, чи можна поставити ферзя в комірку «new_column»/«new_row» так,
# аби не ставити під удар вже розміщенні ферзі
def no_conflict(new_row, new_column, solution):
    # Переконатись, що новий ферзь не знаходиться на одній колонці або діагоналі
    for row in range(new_row):
        if solution[row]         == new_column  or         # Збігаються колонки
           solution[row] + row == new_column + new_row or  # Збігається діагональ
           solution[row] - row == new_column - new_row:    # Збігається діагональ
                return False
    return True

Цей рекурсивний алгоритм можна перетворити на ітеративний алгоритм без рекурсії.

Реалізація задачі про вісім ферзів на мові програмування С++

#include "stdafx.h"
#include <iostream> 
using namespace std;
              
int main(){

        int q[8],c,i;
        int count = 1;
        q[0] = 0;
        c = 0;
      

NC:
        c++;
        if(c == 8) goto print;
        q[c] = -1;
              

NR:
        q[c]++; 
        if(q[c] == 8) goto back;
        
        for (i = 0; i < c; i++) {
                if((q[i] == q[c]) || ((c - i) == abs(q[c] - q[i]))) goto NR;}
        goto NC;


back:
        c--;
        if (c == -1) return 0;
        goto NR;

print:
        cout << endl;
        cout << "#" << count << endl;
        for(i = 0;i < 8; i++){
                cout << q[i] << " ";
        }
        cout << endl;
        count++;
        goto back;
        system("pause");

        return 0;
}


Програмування в обмеженнях

Засобами програмування в обмеженнях в обмеженій області визначення можна сформулювати задачу про ферзів компактніше.

Наступна програма мовою Пролог (діалект GNU Prolog) швидко знаходить розв'язок і для задач на більших шахівницях.

 /* Цей предикат створює список, який відповідає розв'язку задачі.
    Список містить числа від 1 до N без повторів. */
 n_queens(N,Ls) :- length(Ls,N),
                fd_domain(Ls,1,N),
                fd_all_different(Ls),
                constraint_queens(Ls),
                fd_labeling(Ls,[variable_method(random)]).

 /* Цей предикат вірний, якщо розміщення ферзів
    задовольняє умовам задачі */

 constraint_queens([]).
 constraint_queens([X|Xs]) :- not_beats(X,Xs,1), constraint_queens(Xs).

 /* Цей предикат вірний, якщо дві дами не стоять на одній
    діагоналі */

 not_beats(_,[],_).
 not_beats(X,[Y|Xs],N) :- X#\=Y+N, X#\=Y-N, T#=N+1, not_beats(X,Xs,T).

Розв'язки

Класична задача

Всього задача про вісім ферзів має 92 розв'язки, але відкинувши розв'язки, які можна отримати відбиттям (віддзеркаленням позиції) та обертанням (обертанням позиції на шахівниці) лишиться 12 унікальних розв'язків. Оскільки кожен унікальний розв'язок має чотири відбиття (через діагональ, горизонталь, вертикаль, та середину шахівниці), та чотири повороти, можна отримати 8·12 = 96 розв'язки. Оскільки один з розв'язків (діаграма № 12), залишається незмінним при повороті на 180°, з нього можна отримати лише чотири розв'язки. Завдяки йому, загальна кількість розв'язків класичної задачі дорівнює 92.

Нижче наведено унікальні розв'язки задачі для 8 ферзів.

abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 1
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 2
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 3
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 4
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 5
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 6
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 7
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 8
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 9
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 10
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 11
abcdefgh
8
8
77
66
55
44
33
22
11
abcdefgh
Унікальний розв'язок № 12

Узагальнена задача

Узагальнена задача про ферзів полягає в розміщенні n ферзів на шахівниці розміром n × n.

Кількість розв'язків на шахівницях до 26 × 26

В наступній таблиці наведено кількість унікальних розв'язків та загальну кількість розв'язків для задач про ферзі на шахівницях розміром до 26 × 26.


n 123456789101112131415161718
унікальних 10012161246923411 787923345 752285 0531 846 95511 977 93983 263 591
взагалі 10021044092352724268014 20073 712365 5962 279 18414 772 51295 815 104666 090 624
n 192021222324
унікальних 621 012 7544 878 666 80839 333 324 973336 376 244 0423 029 242 658 21028 439 272 956 934
взагалі 4 968 057 84839 029 188 884314 666 222 7122 691 008 701 64424 233 937 684 440227 514 171 973 736
n 25 (світовий рекорд 2005 р.)26 (світовий рекорд 2009 р.)
унікальних 275 986 683 743 4342 789 712 466 510 289
взагалі 2 207 893 435 808 35222 317 699 616 364 044

На той час відома, але не перевірена кількість розв'язків для n = 12, була підтверджена 1969 р. незалежно Торбьорном Ліндельофом (нім. Torbjörn Lindelöf) та Берндом Шварцкопфом (нім. Bernd Schwarzkopf) на комп'ютері. Ліндельофу також вдалось обчислити кількість розв'язків для n = 13 та n = 14[2]. 1970 р. Ліндельофу вдалось обчислити кількість розв'язків для n = 15[3].

Кількість розв'язків для n = 26 була обчислена 11 липня 2009 р. проектом Queens@TUD[4] із використанням FPGA-процесорів, а 30 серпня 2009 р. була підтверджена проектом MC#[5]на двох російських суперкомп'ютерах зі списку TOP500.

Взагалі, можна стверджувати, що кількість розв'язків зростає дещо швидше за експоненційну. Слід відмітити, що кількість розв'язків для шахівниць 2 × 2 та 6 × 6 менша, аніж на шахівницях меншого від них розміру.

Кількість розв'язків для довільних n

Верхня границя кількості розв'язків D(n) задачі розміру n дорівнює n!, що дорівнює кількості розв'язків для n тур. Кількість ферзів, які не ставлять під удар одна одну, набагато менша за це число.

Асимптотична форма для D(n) не відома. Рівін та інші припускають, що[6]:

.

Відомі результати дозволяють ще більше звузити оцінку для великих n до[7]: , де .

Див. також

Примітки

  1. O.-J. Dahl, Edsger W. Dijkstra, C. A. R. Hoare Structured Programming, Academic Press, London, 1972 ISBN 0-12-200550-3
  2. Karl Fabel: Das n-Damen-Problem. In: Die Schwalbe, Heft 1, Oktober 1969. S. 20
  3. Karl Fabel: Das n-Damen-Problem. In: Die Schwalbe, Heft 5, September 1970. S. 146
  4. Queens@TUD, TU Dresden, Deutschland. Архів оригіналу за 10 листопада 2017. Процитовано 13 квітня 2019.
  5. MC#-Projekt. Архів оригіналу за 1 березня 2012. Процитовано 3 січня 2011.
  6. I. Rivin, I. Vardi, P. Zimmermann: The n-Queens Problem. In: The American Mathematical Monthly. Band 101, 1994, S. 629—639
  7. послідовність A000170 з Онлайн енциклопедії послідовностей цілих чисел, OEIS

Література

  • John J. Watkins: Across the Board: The Mathematics of Chess Problems. Princeton University Press, Princeton 2004, ISBN 0-691-11503-6.

Посилання

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.