Алгоритм танцевальных ссылок - объяснение, которое менее объяснимо, но больше о реализации?

Я работаю над Sudoku Solver, мой текущий решатель использует алгоритм обратного отслеживания, но он все еще занимает слишком много времени.

Я надеюсь, что в большинстве случаев это будет меньше секунды. Таким образом, я решил переписать его с помощью алгоритма танцевальных ссылок, понимая, что это один из лучших методов bruteforce, который хорошо работает с проблемой ограничения, такой как головоломка Sudoku.

Я попытался прочитать Wiki и кнутскую бумагу на нем, однако оба они довольно трудно понять и чрезвычайно многословно.

Я также читаю версию Sudopedia на нем, и кажется, что как только он попал в реализацию Sudoku, он стал слишком абстрактным.

Может кто-нибудь попытаться объяснить алгоритм Dancing Links не в терминах его вывода, а в его реализации? (было бы здорово использовать Судоку в качестве примера)

Спасибо!

Ответы

Ответ 1

Возможно, вас заинтересует моя реализация в javascript.


Во-первых, вы должны понимать Точную обложку. Точная проблема с обложкой - это проблема, когда вам дают кучу вариантов, а набор ограничений и ваша задача - выбрать кучу вариантов, которые будут заполнять каждое ограничение ровно один раз.

Например, рассмотрим случай, когда кто-то создает свою ледяную танцевальную рутину. У них есть несколько трюков, которые им нужно показать судьям, и не хотят делать какой-либо трюк более одного раза. У них есть ряд последовательностей, которые представляют собой группы трюков, которые можно собрать вместе, и они хотят выбрать идеальный выбор последовательностей для покрытия всех трюков один раз. В этом примере ограничения заключаются в том, что они должны выполнять каждый трюк. Выбор - возможные последовательности, которые они могут включить в свою рутину.

Хорошим способом представления проблем такого рода является извлечение таблицы, где ограничения являются столбцами, а выбор - это строки, и у вас есть большой X в ячейках, где конкретный выбор выполняет это ограничение.

Как оказалось, с учетом правильных ограничений и выбора судоку можно охарактеризовать как проблему с точной оболочкой.


Хорошо, предполагая, что у вас это есть, теперь вам нужно понять Алгоритм X. Кнут сказал об этом. "Алгоритм X - это просто утверждение очевидного метода проб и ошибок (действительно, я не могу думать о каких-либо других разумный способ выполнить эту работу в целом.)". Итак, здесь мое описание алгоритма X:

  • Если в таблице нет столбцов, остановитесь - вы ее решили. Если у вас есть частичное решение, то оно действительно реальное решение, верните его.
  • Выберите столбец (представляющий ограничение).
  • Найти строку с крестом в этом столбце (представляющий выбор, который выполняет это ограничение). Добавьте его в какую-то структуру, где вы храните потенциальные решения. Если вы не можете найти строку, сдайтесь - решений нет.
  • Предположим, что строка, найденная вами в 3, находится в решении, поэтому удалите все столбцы, в которых есть X в этой строке. При удалении всех этих столбцов также удалите все строки, у которых есть X в столбцах, которые вы удаляете (поскольку вы уже удовлетворили ограничение, поэтому вам запрещено выбирать что-то, что удовлетворит его снова).
  • Теперь рекурсивно попытаемся решить приведенную таблицу. Если вы не можете, удалите строку, которую вы попробовали, из потенциальной структуры решения, восстановите все строки и столбцы, которые вы удалили на шагах 3 и 4, и попробуйте другую строку. Если у вас заканчиваются ряды, то сдайтесь - решений нет.

Теперь, когда вы это понимаете, вы можете понять танцевальные ссылки. Dancing Links - это способ эффективного выполнения этого алгоритма. Ключевым моментом танцевальных ссылок является то, что в связанном списке, когда вы удаляете node (что может быть сделано эффективно, изменяя указатели его соседей), node, который вы удалили, имеет всю необходимую вам информацию чтобы добавить его обратно в связанный список (в случае, если окажется, что вы ошибались, когда вы догадались, что это часть решения). Это плюс тот факт, что если вы сделаете все свои связанные списки круговыми, то вдруг вы потеряете много особых случаев, почти все танцевальные ссылки.

Ответ 2

Хотя этот вопрос очень старый, я подумал, что добавлю:

Эта страница делает алгоритм очень понятным: Zendoku writeup. Пока я не прочитал об этом по этой ссылке, я подумал, что это должен быть супер-продвинутый алгоритм, но на самом деле, когда вы можете визуализировать его, это просто оригинальное, но простое решение.

Также моя реализация на С# должна быть довольно легко читать... было бы полезно разделить различные классы на разные файлы, я уверен.
Это в значительной степени прямая реализация от Knuth pdf, но с несколькими объектно-ориентированными оптимизациями (на самом деле, так как я сделал это несколько месяцев назад, я не совсем помню, как сильно я отклонился от pdf)