Несколько лет назад я взял курс алгоритмов, где мы задавали следующую проблему (или такую, как она):
Существует здание этажей
n
с лифтом, который может подниматься только на 2 этажа одновременно и вниз по 3 этажа за раз. Используя динамическое программирование, напишите функцию, которая будет вычислять количество шагов, которые требуется для подъема лифта от полаi
до полаj
.
Это, очевидно, легко, используя подход, основанный на состоянии, вы создаете массив n элементов длиной и заполняете его значениями. Вы даже можете использовать технически не-stateful подход, который предполагает накопление результата, рекурсивно передавая его. Мой вопрос заключается в том, как сделать это неконфессионально, используя ленивую оценку и привязывая узел.
Я думаю, что я разработал правильную математическую формулу:
где i+2
и i-3
находятся в пределах допустимых значений.
К сожалению, я не могу закончить его. Если я сначала поставлю случай i+2
, а затем выберите ровный пол, я получу его, чтобы оценить ровные этажи ниже целевого уровня, но это. Я подозреваю, что он стреляет прямо на самый высокий ровный пол для всего остального, падает на 3 уровня, затем повторяет, навсегда колеблется между верхними несколькими этажами.
Поэтому он, вероятно, сначала исследует бесконечное пространство (или конечное, но с петлями) в глубину. Я не могу придумать, как исследовать пространство в первом порядке, не используя множество структур данных между ними, которые эффективно имитируют подход с учетом состояния.
Хотя эта простая проблема неутешительно сложна, я подозреваю, что, увидев решение в 1 измерении, я мог бы заставить его работать для двумерного изменения проблемы.
EDIT: многие ответы пытались решить проблему по-другому. Сама проблема не интересна мне, вопрос в том, какой метод используется. Подход хаосматера к созданию функции minimal
, которая может сравнивать потенциально бесконечные числа, возможно, является шагом в правильном направлении. К сожалению, если я попытаюсь создать список, представляющий здание с 100 этажами, результат будет слишком долгим для вычисления, поскольку решения для подпрограмм не будут повторно использоваться.
Я попытался использовать структуру данных с саморефлексией, но она не заканчивается, происходит какой-то бесконечный цикл. Я отправлю свой код, чтобы вы могли понять, для чего я это делаю. Я изменю принятый ответ, если кто-то действительно сможет решить проблему, используя динамическое программирование в самореферентной структуре данных, используя лень, чтобы избежать вычисления вещей более одного раза.
levels = go [0..10]
where
go [] = []
go (x:xs) = minimum
[ if i == 7
then 0
else 1 + levels !! i
| i <- filter (\n -> n >= 0 && n <= 10) [x+2,x-3] ]
: go xs
Вы можете увидеть, как 1 + levels !! i
пытается ссылаться на ранее вычисленный результат и как filter (\n -> n >= 0 && n <= 10) [x+2,x-3]
пытается ограничить значения i
допустимыми. Как я уже сказал, это фактически не работает, оно просто демонстрирует метод , с помощью которого я хочу, чтобы эта проблема была решена. Другим способом ее решения является не.