Обход шахматной доски конем
Рассмотрим конкретное воплощение абстрактной схемы 3 для известной задачи об обходе конем шахматной доски размера nn. Будем считать, что строки и столбцы доски пронумерованы соответственно сверху вниз и слева направо цифрами от 0 до n – 1, а конь перемещается по доске согласно обычным шахматным правилам. Найти обход доски с конкретного поля означает, что нужно найти последовательность позиций перемещения коня такую, что каждое поле посещается им ровно один раз. Для доски 88 эта задача впервые была поставлена Л. Эйлером.
Постановка задачи. На шахматной доске размера nn в позиции (x, y) находится конь (см. рис. 1). Составить рекурсивную программу-функцию, находящую методом перебора с возвратом обход доски конем, если он существует. При отсутствии обхода должно быть выдано соответствующее сообщение.
Решение. На рис.1 приведен фрагмент доски. Конь K стоит в позиции (x, y). Клетки с цифрами вокруг K – это поля, на которые конь может переместиться из (x, y) (0 x, y n – 1) за один ход. Множество этих полей обозначим через M(x,y). Для фиксированного поля (x, y) множество M(x, y) может содержать от двух до восьми элементов. Попробуем упорядочить эти множества. Рассмотрим вспомогательную матрицу приращений
(1)
Для поля (x, y) построим последовательность полей
(2)
и отберем из них те, для которых
0 x + D0,k n – 1 и 0 y + D1,k 0 (k = 0, 1, …, 7) (3)
Рис.1. Схема упорядочивания множества возможных ходов коня.
Именно эти поля и составляют множество M(x, y). Каждому элементу (a, b)M(x,y) припишем номер K столбца D, элементы которого в соответствии с (2) и (3) задают приращения по осям для перемещений коня из (x, y) в (a, b). Таким образом, возможные ходы коня из (x, y) упорядочены по полученным ими номерам. На рис.1 эти номера проставлены в соответствующих клетках. Заметим, что иные варианты матрицы D, а всего их 8! = 40320, дают иные способы упорядочивания M(x, y).
Решая поставленную задачу с помощью общей схемы 3 перебора с возвратом, мы должны последовательно формировать вектор длины n. Нам удобней строить не вектор, а матрицу размера nn, отмечая в её клетках номера ходов коня от единицы до n2. В приложении приведено определение функций HTour и HMain на языке Pascal, реализующих данный алгоритм.
В каждом рекурсивном вызове глубины j делается попытка поместить коня в очередное j-е поле доски. Позицию, из которой коня продвинуть дальше нельзя, назовем тупиком. Попадание в тупик приводит к завершению текущего рекурсивного вызова, то есть к возврату к предыдущему полю и продолжению работы с ним. Иных случаев завершения рекурсивных вызовов не существует.
Поэтому базой рекурсии нужно считать совокупность всех тупиков. Элементы базы заранее, до вычислений, неизвестны. Если в очередном рекурсивном вызове продвинуть коня удается, то осуществляется переход к следующему рекурсивному вызову. Если удается продвинуть коня на последнюю из незанятых клеток n, то осуществляются последовательные возвраты на первый рекурсивный уровень (j = 0) и возвращается решение. Если осуществлен возврат на первый рекурсивный уровень при незаполненной доске, и на этом уровне уже испытаны все допустимые ходы, то выдается сообщение об отсутствии решений.
Следствие. Попытки решать задачу при n > 8 с помощью функций программы Horse наталкиваются на сложности, связанные с недостатком памяти или продолжительностью вычислений. Поэтому для решения задачи даже для обычной шахматной доски (n = 8) требуются какие-либо иные подходы.
