Вирішення субпроблем динамічного програмування


39

Я неодноразово використовував техніку динамічного програмування, проте сьогодні друг запитав мене, як я берусь щодо визначення своїх субпроблем, я зрозумів, що не можу дати об'єктивну формальну відповідь. Як ви формально визначите підпроблему для проблеми, яку ви вирішили, використовуючи динамічне програмування?


Схоже, жодна з існуючих відповідей (станом на квітень 2019 року) не є достатньо хорошою, особливо для початківців. Я б порекомендував підручники на інших сайтах.
Apass.Jack

Відповіді:


35

Принцип динамічного програмування полягає в тому, щоб думати зверху вниз (тобто рекурсивно), але вирішувати знизу вгору. Тож хороша стратегія проектування ПЗ полягає в формулюванні проблеми рекурсивно та генеруванні підпроблем таким чином.


14
Я стверджую, що це єдина стратегія.
JeffE

2
@JeffE Так, я читав і використовував ваші замітки під час викладання моїх класів алгоритму, і це було ефективно. Цитата: "Динамічна справа не в заповненні таблиць. Це в розумній рекурсії!"
Дай

2
На моє розуміння того, як навчати ДП сильно впливають записки @ JeffE :)
Суреш

3
Також можливо автоматично перетворити рекурсивну процедуру зверху вниз в алгоритм динамічного програмування. Коли ви збираєтеся повернутися, зберігайте відповідь у хеш-таблиці. На початку кожного дзвінка перевірте, чи відповідь уже є у хеш-таблиці, і якщо так, негайно поверніть її. Багато алгоритмів стають простими з цією ідеєю. Наприклад, з такою таблицею рекурсивні алгоритми спроб автоматично працюють на DAWG. Зберігаючи значення дозорного в таблиці на початку дзвінка, ті ж алгоритми можуть працювати навіть у DFA. Алгоритми на BDD стають дуже просто задати рекурсивно.
Жуль

1
Не в останню чергу, це може мати величезні переваги в роботі. Наприклад, традиційний алгоритм суми підмножини знизу вгору може обчислити багато непотрібних записів таблиці. За допомогою цього методу будуть обчислюватися лише необхідні записи таблиці.
Жуль

4

Як зазначав @Suresh, як тільки ви знаєте, що вашу проблему можна вирішити DP (тобто вона демонструє оптимальну підструктуру та перекриваючі підпрограми), ви можете подумати про розрив та підкорити рекурсивне рішення.

Звичайно, поділ і підкорення буде сильно неефективним, оскільки кожна підпроблема, що зустрічається у відповідному дереві рекурсії, буде вирішена знову, навіть якщо вона вже знайдена та вирішена. Тут DP відрізняється: кожного разу, коли ви стикаєтеся з підпрограмою, ви вирішуєте її і зберігаєте її рішення в таблиці. Пізніше, коли ви знову зустрінете цю підпроблему, ви отримаєте в раз її рішення замість того, щоб знову її вирішити. Оскільки кількість підпроблем, що перекриваються, як правило, обмежується поліномом, а час, необхідний для вирішення однієї підпрограми, є і многочленом (інакше DP не може забезпечити економічно ефективне рішення), ви в цілому досягаєте поліноміального рішення.O(1)

Тому роздуми над рішенням про розрив та перемогу нададуть вам уявлення про те, якою може бути підпроблема для вашої конкретної проблеми.


1
"оптимальна підструктура" (що б це не означало), ймовірно, не є достатньою умовою для вирішуваності DP. "Субпроблеми, що перекриваються", безумовно, не є необхідними.
Рафаель

1
Оптимальна підструктура та перекриваються надпрограми проявляються проблемами, які можна ефективно вирішити за допомогою DP. Звичайно, самої оптимальної підструктури недостатньо для розв’язання DP. Однак якщо у вас немає підпроблем, що перекриваються, ви можете вирішити проблему звичайним діленням і перемогою з однаковою вартістю: дійсно, перевага DP перед розділенням conquer полягає в тому, що кожна підпроблема вирішується рівно один раз, коли виникає в дереві рекурсії. .
Массімо Кафаро

1
Це не моє формулювання: ви знайдете його у "Вступі до алгоритмів" Кормена, Лейзерсона, Рівеста та Штейна та в багатьох інших підручниках з алгоритмів.
Массімо Кафаро

1
Юп, і більшість принаймні частково помиляються. Я радий деталізувати, якщо ви опублікуєте відповідне запитання.
Рафаель

1
Я не впевнений, що я правильно розумію ваш останній коментар. Щоб показати, що така характеристика неправильна (вона частково не може бути помилковою: або вона правильно, або неправильна), ви можете просто показати як контрприклад, проблема, яка не проявляє як оптимальної підструктури, так і перекриваючих підпроблем, але є піддається поліноміальному розчину DP. Але зауважте, що в цьому контексті це означає рішення, яке, мабуть, краще, ніж звичайні розділення та перемоги.
Массімо Кафаро

2

Мій досвід полягає у пошуку способу "скоротити надмірне перерахування за допомогою збереження вже переліченого корисного значення". До речі, динамічне програмування дійсно популярне в ICPC (Міжнародний конкурс колегіального програмування. Кожен може мати власне відчуття щодо ДП після практики декількох проблем МКПК.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.