Чем динамическое программирование отличается от жадных алгоритмов?

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

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

поскольку оба включают локальную оптимальность, не является ли одно подмножеством другого?

7 ответов


динамическое программирование применимо к задачам, демонстрирующим свойства:

  • перекрывающиеся подзадачи и
  • оптимальная подструктура.

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

этот ответ привлек некоторое внимание, поэтому я приведу несколько примеров.

рассмотрим проблему "внесение изменений в долларах, пятаки и копейки.- Это жадная проблема. Он показывает оптимальную подструктуру, потому что вы можете решить для количества долларов. Затем решите для количества пятицентовиков. Тогда число пенсы. Затем можно эффективно объединить решения этих подзадач. На самом деле он не показывает перекрывающихся подзадач, так как решение каждой подзадачи не очень помогает с другими (возможно, немного).

рассмотрим проблему "цифры Fibonnaci."Он демонстрирует оптимальную подструктуру, потому что вы можете решить F(10) из F(9) и F(8) эффективно (путем добавления). Эти подзадачи перекрываются, потому что они оба разделяют F(7). Если вы запомните результат F (7), Когда вы решаете F (8), вы можете решить F(9) быстрее.

в ответ на комментарий о динамическом программировании, связанном с "пересмотром решений": это, очевидно, не верно для любого алгоритма линейного динамического программирования, такого как максимальная проблема subarray или проблема Фибоначчи выше.

по существу, представьте себе проблему, имеющую оптимальную подструктуру в виде направленного ациклического графа, узлы которого представляют подзадачи (где вся проблема представлена узел, чьи indegree равна нулю), и которой направлена ребер обозначают зависимости между подзадачами. Затем, жадной проблема-это дерево (все узлы за исключением корня имеют блок indegree). Проблема динамического программирования имеет некоторые узлы с indegree больше одного. Это иллюстрирует перекрывающиеся подзадачи.


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


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

выбор, сделанный жадным алгоритмом, может зависеть от выбора, сделанного до сих пор, но не от будущих выборов или всех решений подзадачи. Он итеративно делает один жадный выбор за другим,уменьшая каждую данную проблему в меньшую. Другими словами, жадный алгоритм никогда не пересматривает своих решений. Это основное отличие от динамического программирования, которое является исчерпывающим и гарантированно найдет решение. После каждого этапа динамическое программирование принимает решения, основанные на решения, принятые на предыдущем этапе, и могут пересмотреть алгоритмический путь предыдущего этапа к решению.


алгоритмы DP используют тот факт, что (для некоторых задач) - оптимальное решение задачи размера n состоит из оптимального решения задачи размера n'<n, и использует это для построения решения снизу вверх, от наименьшей проблемы до требуемого размера.

Он очень хорошо подходит к тому же принципу рекурсии (уменьшите проблему до меньшей подзадачи и вызовите рекурсивно), и действительно-решения DP часто представлены как рекурсивные формула.

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

хорошим примером различий между двумя подходами является для проблема кратчайшего пути:

  • Dijsktra это - жадный подход (на каждом шаге, выбрал узел, путь к которому в данный момент минимизирован - выбор делается жадно исходя из локального состояния алгоритма).
  • алгоритм Беллмана-Форда является решением DP ("расслабить" все края, эффективно уменьшая проблему)

жадный метод:

  1. жадный метод фокусируется на расширении частично построенного решения.
  2. оно обеспечивает много результатов как возможное решение.
  3. более эффективным!--4-->

динамическое программирование:

  1. фокусируется на принципе оптимальности.
  2. оно дает конкретные ответы.
  3. менее эффективным!--4-->

разница между DP и greedy-DP будет искать глобальный Оптимал в каждой подзадаче, но greedy будет искать только локальный Оптимал. Итак, об этом сценарии:

Предположим, вы поднимаетесь на гору, и вы хотите подняться как можно выше. Дорога на горе имеет несколько ответвлений, и на каждом перекрестке вам нужно решить, какую ветку взять, что является подзадачей этой проблемы восхождения (цель та же, только начальная точка разные)

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

для DP на каждом пересечении вы уже должны знать самую высокую высоту, на которую приведет вас каждая ветвь (предположим, что ваш порядок оценки отменен, a.к. a от конечных точек до начальной точки), и выберите тот, который имеет наибольшую высоту. Это решение принято. по глобальному оптимуму будущих подзадач и там Для будет оптимальный для этой подзадачи


концепции жадных и динамических решений не являются взаимоисключающими, и я думаю, что это вызывает много путаницы в большинстве ответов. Я считаю, что ответ Амита подчеркивает самое важное свойство: жадное решение принимает решения, основанные на local информация. Как следствие, жадное решение может в конечном итоге найти local оптимальный вместо глобального. Динамические решения разбивают задачу на более мелкие подзадачи, а затем агрегируют результат в получите ответ на более сложную проблему. Итак-возможно ли, что проблема заключается в обоих динамический и жадина? Ответ - да, это возможно. Примером может служить алгоритм Дейкстры. Для этого алгоритма вы делаете жадный выбор на каждом шаге, и все же вы сводите проблему к более простой подзадаче.

еще есть примеры жадных алгоритмов, которые не являются DP - s: скажем, hill climbing-это жадный алгоритм, который не ломает проблему в несколько подзадач-он всегда решает только одну. Есть также примеры DPs, которые не являются жадными-например, вычисление n-го числа Фибоначчи с помощью memoization не является жадным.