Что такое динамическое программирование? (Методы и примеры)
6 мая 2021 г.
Динамическое программирование — это метод платежеспособности, который может помочь упростить процессы, содержащие несколько подзадач. Поскольку динамическое программирование может помочь оптимизировать процесс кодирования для многих компьютерных приложений, профессионалы в области анализа данных, программирования и разработки программного обеспечения часто применяют этот процесс для оптимизации своей работы. Если вы вступаете в должность, требующую навыков программирования и кодирования, полезно понять, как вы можете интегрировать динамическое программирование в свои проекты. В этой статье мы исследуем, что такое динамическое программирование, каковы характеристики динамического программирования и какие методы использовать при решении задач рекурсивного кодирования с помощью динамического программирования.
Что такое динамическое программирование?
Динамическое программирование — это алгоритмический процесс, который компьютерные инженеры и программисты используют для решения задач оптимизации. Например, при интеграции динамического программирования в проект разработки программного обеспечения алгоритм, который использует DP, разбивает сложные проблемы кодирования на подзадачи. Затем программисты могут применить оптимизированное решение ко всей проблеме в зависимости от типа решения, которое они получают из каждой подзадачи в коде.
Кроме того, динамическое программирование оптимизирует простую рекурсию с помощью рекурсивных решений, которые программисты получают путем вычислений подзадач задачи. Этот процесс оптимизации помогает устранить необходимость повторного вычисления входных данных позже, когда это необходимо для внедрения нового кода в ваш проект.
Программы для Windows, мобильные приложения, игры - ВСЁ БЕСПЛАТНО, в нашем закрытом телеграмм канале - Подписывайтесь:)
Характеристики динамического программирования
Динамическое программирование обладает двумя важными характеристиками, которые делают его жизнеспособным и эффективным инструментом для сокращения времени программирования и повышения функциональности и эффективности программы:
Подзадачи перекрываются
Подзадачи — это просто меньшие вариации исходной, более крупной проблемы. Например, в последовательности Фибоначчи каждое число в ряду является суммой двух предшествующих ему чисел (0, 1, 1, 2, 3, 5, 8 и т. д.). Если вы хотите вычислить n-е значение Фибоначчи в последовательности, вы можете разбить всю задачу на более мелкие подзадачи. Затем эти подзадачи перекрываются друг с другом, поскольку вы находите решения, многократно решая одну и ту же подзадачу. Перекрытие подзадач происходит с любой проблемой, что позволяет применять динамическое программирование для разбиения сложных программных задач на более мелкие части.
Подструктура имеет оптимальное свойство
Если вы можете прийти к оптимальному решению, которое вы строите из всех оптимальных решений, найденных при решении каждой подзадачи, то вся проблема демонстрирует свойство оптимальной подструктуры. Это означает, что при решении каждой подзадачи решение, которое вы вычисляете из каждого перекрытия, должно применяться ко всей проблеме, чтобы функционировать и оптимизировать рекурсию в вашем программировании. В примере последовательности Фибоначчи каждая подзадача содержит решение, которое можно применить к каждой последующей подзадаче, чтобы найти следующее число в ряду, заставив всю задачу отображать свойство оптимальной подструктуры.
Методы динамического программирования
Применяя динамическое программирование к своим проектам, вы можете реализовать два метода:
Нисходящий метод
В нисходящем методе динамического программирования вы решаете общую проблему, прежде чем разбивать ее на подзадачи. Этот процесс представляет собой запоминание и работает для решения более крупных проблем путем рекурсивного поиска решения подзадач с кэшированием каждого результата. Этот процесс запоминания помогает избежать повторного решения проблемы, если вам нужно вызвать ее более одного раза. С помощью метода «сверху вниз» вы можете просто вернуть результат, который вы сохранили при решении общей проблемы, сохраняя, таким образом, результаты уже решенных вами проблем.
Восходящий метод
В восходящем методе (или методе табуляции) вместо применения рекурсии вы сначала решаете все связанные подзадачи. Поскольку восходящее табулирование требует нескольких платежеспособностей, динамическое программирование использует многомерную таблицу или n-мерную таблицу, где n представляет собой значение, равное нулю или больше. Когда вы решаете каждую подзадачу в таблице, вы можете использовать результаты для вычисления исходной задачи.
Примеры динамического программирования
Чтобы понять, как вы можете применить оба метода динамического программирования, используйте следующий пример, чтобы применить процесс к последовательности Фибоначчи:
Пример сверху вниз
Примените последовательность Фибоначчи, где каждое число в ряду представляет собой сумму первых двух предыдущих чисел:
{0, 1, 1, 2, 3, 5, 8,…}
Понимание того, что сумма первых двух предыдущих значений будет следующим числом в ряду, может помочь вам решить всю проблему, когда вы хотите вычислить n-е число Фибоначчи. Поскольку вы знаете шаблон для вычисления будущих значений в ряду, вы можете применить формулу для определения оптимального решения, не разбивая проблему на более мелкие подзадачи. Используя соответствующую формулу, когда n > 1, вы можете вычислить оптимальное решение с помощью нисходящего метода при решении для n-го значения 13:
Фиб (n) = Фиб (n – 1) + Фиб (n – 2) =
Фибоначчи (13) = Фибоначчи (13 – 1) + Фибоначчи (13 – 2) =
Фибоначчи (n) = Фибоначчи (12) + Фибоначчи (11) = 23
Используя нисходящий подход и применяя мемоизацию, вы можете кэшировать результат 23 в базе данных, если вам потребуется ввести и вызвать строку кода для дополнительных задач.
Пример снизу вверх
В этом примере примените последовательность Фибоначчи, как и ранее, чтобы разбить все вычисления, когда вы хотите вычислить n-е значение в ряду. С той же числовой последовательностью {0, 1, 1, 2, 3, 5, 8,…} вы можете видеть, что следующее значение в ряду дает 13, так как пять и восемь дают сумму 13. Используя восходящий метод, чтобы разрушить всю проблему Fib (n), вы применяете уравнение последовательности [Fib(n – 1) + Fib(n – 2), when n > 1] для каждой подзадачи, для которой вы хотите найти оптимальное решение. Предположим, вы хотите вычислить следующие n-е значения, когда n = 23:
Фиб (n) = Фиб (n – 1) + Фиб (n – 2) =
Фибоначчи (23) = Фибоначчи (23 – 1) + Фибоначчи (23 – 2) =
Фибоначчи (23) = Фибоначчи (22) + Фибоначчи (21) = Фибоначчи (43)
Затем результат Fib(43) применяется к вычислению следующих значений в ряду, когда n = 43:
Фиб (n) = Фиб (n – 1) + Фиб (n – 2) =
Фибоначчи (43) = Фибоначчи (43 – 1) + Фибоначчи (43 – 2) =
Fib(n) = Fib(42) + Fib(41) = Fib(83), тогда
Фибоначчи (83) = Фибоначчи (83 – 1) + Фибоначчи (83 – 2) =
Фибоначчи (83) = Фибоначчи (82) + Фибоначчи (81) = Фибоначчи (163)
Вы можете продолжать использовать это оптимальное решение для каждой подзадачи для вычисления следующих значений в последовательности Фибоначчи, что дает вам возможность разбить исходную проблему Fib (n) = Fib (n – 1) + Fib (n – 2), когда п > 1.