Напишите функцию / подпрограмму для сортировки списка целых чисел, стиль Ханойской башни .
Вы получите стек целых чисел. Это основной стек.
Вам также дают еще два стека помощников. Эти вспомогательные стеки имеют уникальное свойство: каждый элемент должен быть меньше или иметь тот же размер, что и элемент под ним. Основной стек не имеет такого ограничения.
Вам поручено отсортировать основной стек на месте, поместив под ним самые большие целые числа. Ваша функция / подпрограмма будет возвращать (или эквивалентно) количество ходов, которые она сделала при сортировке стека.
Примечание: вы должны отсортировать основной стек на месте , не сортируя на другой стек и вызывая этот ответ. Однако, если вы по какой-то причине не можете этого сделать, вы можете смоделировать изменяемые стеки, но помните, что это Ханойская башня; Есть только 3 колышка, и только 1 колышек может быть неупорядоченным.
Ваша функция / подпрограмма может проверять любой стек в любое время, но она может только сделать движение, щелкая и толкая. Один ход - это поп из одного стека, который перемещается в другой.
Проверьте свою функцию / подпрограмму для каждой перестановки первых 6 натуральных чисел. Другими словами, проверьте свою функцию / подпрограмму {1},{2},...,{6},{1,1},{1,2},...,{1,6},{2,1},...
(это должно быть всего или возможностей (спасибо Говарду за исправление моей математики)). Функция / подпрограмма, которая перемещает элементы, выигрывает наименьшее количество раз.61+62+...+66
55986
источник
6**1+6**2+...+6**6=55986
элементы.Ответы:
Java - оптимальное решение (1080544 ходов)
Это решение создает дерево кратчайшего пути от цели и обратно, а затем пересекает путь от начального состояния к цели. Много места для улучшения скорости, но это все равно решает все 55986 проблем примерно за минуту.
Предполагая, что алгоритм правильно реализован, это должно быть теоретически лучшим решением.
источник
C - 2547172 для 55986 входов
Здесь есть много возможностей для совершенствования. Для собственного здравого смысла я упростил это, чтобы можно было проверять только верхний элемент каждого стека. Снятие этого добровольного ограничения позволило бы оптимизировать, например, заранее определить конечный заказ и попытаться свести к минимуму количество ходов, необходимых для его достижения. Убедительным примером является то, что моя реализация ведет себя в худшем случае, если основной стек уже отсортирован.
Алгоритм:
Анализ:
источник
Python,
39838383912258 движется через 55986 входовЭто очень неэффективно.
Я добавлю общее количество ходов после того, как ОП уточнит, предназначены ли они для всех этих случаев или для конкретных других случаев.
объяснение
Что, комментарии не достаточно хороши для вас?
Примечание для ОП: Спасибо, что не сделали этот код-гольф.
источник
[2,1,1]
есть ли способ получить[2,1,1].index(1)
как 2, то есть начиная с более высокого конца?[2,1,1,3,5].index(1)==2
вместо1
list.index(data)
возвращает индекс элементаdata
вlist
. Я не знаю индексdata
ie1
len(list)-(list[::-1].index(1))
Питон:
16882931579182152405414508421093195 ходовОсновной метод заключается в том
main_to_help_best
, чтобы переместить некоторые выбранные элементы из основного стека в вспомогательный стек. У него есть флаг,everything
который определяет, хотим ли мы, чтобы он перемещал все в указанноеdestination
, или же мы хотим сохранить только самое большое вdestination
то время, как остальные находятся в другом помощнике.Предположим, что мы переходим к
dst
использованию помощникаhelper
, функцию можно примерно описать следующим образом:helper
рекурсивногоdst
helper
главнойdst
everything
установлено, рекурсивно перемещать элементы в main вdst
b. В противном случае рекурсивно перемещать элементы в главном
helper
Основной алгоритм сортировки (
sort2
в моем коде) будет затем вызыватьсяmain_to_help_best
сeverything
set toFalse
, а затем перемещать самый большой элемент обратно в main, затем перемещать все из помощника обратно в main, сохраняя его отсортированным.Дополнительные пояснения в виде комментариев в коде.
В основном, принципы, которые я использовал:
Принцип 3 реализован, не считая движение, если источником является предыдущий пункт назначения (то есть мы просто переместили main в help1, затем мы хотим перейти от help1 к help2), и далее мы уменьшаем количество перемещений на 1, если мы переместить его обратно в исходное положение (то есть main для help1, затем help1 для main). Кроме того, если все предыдущие
n
ходы движутся с одинаковым целым числом, мы можем на самом деле изменить порядок этихn
ходов. Таким образом, мы также используем это, чтобы уменьшить количество ходов дальше.Это верно, так как мы знаем все элементы в главном стеке, так что это может быть интерпретировано как видение в будущем, что мы собираемся переместить элемент назад, мы не должны делать это движение.
Пробный прогон (стеки отображаются снизу вверх - поэтому первый элемент находится снизу):
Мы видим, что наихудший случай - когда самый большой элемент размещается на втором дне, а остальные сортируются. Из худшего случая мы видим, что алгоритм O (n ^ 2).
Число ходов, очевидно, минимально для
n=1
и,n=2
как мы можем видеть из результата, и я считаю, что это также минимально для больших значенийn
, хотя я не могу доказать это.Больше объяснений в коде.
источник
4
. Что это значит хранить второй по величине элемент на втором помощнике? Что это значит?Java -
21290902083142 перемещается на 55986 массивахСсылка ideone .
Основа для обеспечения правильности алгоритма:
Фактический алгоритм:
Тестовый случай:
источник
C / C ++ Не измерял ходы (колышки: p1, p2, p3). Не знаю, как добавить код C ++, использующий STL (проблема форматирования). Потеря части кода из-за форматов тегов HTML в коде.
Объедините перемещение (n + m) данных из p2 и p3 в p1.
источник
hanoi(...)
функции. Кроме того, у вас есть 2#include
с, которые не компилируются. Пожалуйста, отправьте полный код.