В моей программе реализована общая формула для квадрата 4-го порядка (приведённая в моей статье "Общие формулы магических квадратов", см. конец статьи).
Эта формула составлена в предположении, что квадрат строится из массива, состоящего точно из 16 чисел. Формула в таком случае зависит всего от 7 параметров и проверка выполняется очень быстро.
Тем не менее, эта формула не оптимальная для вычислений. Ниже представлена гораздо более эффективная формула и алгоритм, являющийся разновидностью метода ветвей и границ.
Занумеруем элементы квадрата
так:
Элементы
,
,
,
,
,
,
,
назовем
независимыми, а остальные элементы -
зависимыми, и укажем явные зависимости:
Важным свойством этих зависимостей является то, что каждый элемент зависит лишь от элементов с меньшими номерами и сам при этом имеет минимально возможный номер.
Пусть теперь нам задан массив чисел, из которых мы хотим построить магический квадрат. Алгоритм построения такой:
На любом шаге алгоритма
свободными числами назовем ранее неиспользованные числа. Изначально все данные числа свободны.
Начинаем определение элементов
в их естественном порядке (т.е. для
):
* если
независимый элемент, перебираем все свободные числа в качестве его значения (текущее выбранное значение перестает быть свободным), и переходим к следующему элементу;
* если
зависимый элемент, вычисляем его значение по вышеуказанным формулам и проверяем является ли это значение свободным. Если да, то число становится несвободным, а мы переходим к следующему элементу; если нет - то возвращаемся к предыдущему элементу.
Алгоритм заканчивает работу, если найдены значения всех элементов (в этом случае квадрат построен), или же, если таковые найти не удалось (в этом случае квадрата не существует).
Важно отметить, что для отбрасывания заведомо прохих вариантов, здесь не всегда нужно знать значения всех независимых элементов. Например, элемент
зависит лишь от
,
и
и проверить его значение можно, зная лишь значения этих трех элементов (совершенно неважно, чему равны остальные). Именно поэтому этот элемент имеет номер
и проверяется сразу после того, как становятся известны значения
,
и
. Именно эта идея делает алгоритм эффективным. Причем в своём классе этот алгоритм является самым эффективным (то есть, большего ускорения выжать из этой идеи не получится).
Теперь можно приступать к дальнейшему поиску квадрата
из смитов.
P. S. Дальнейшая оптимизация возможна с учётом того, что если массив содержит элемент 0, то можно считать, что либо
, либо
равен нулю.