Разница между Divide и Conquer Algo и динамическим программированием

В чем разница между Divide and Conquer Algorithms и Dynamic Programming Algorithms? Как два термина отличаются друг от друга? Я не понимаю разницы между ними.

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

Ответ 1

Разделить и покорить

Разделите и покорите работы, разделив проблему на подзадачи, рекурсивно перехватите каждую подзадачу и объедините эти решения.

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

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

Вы можете думать о DP = recursion + re-use

Классическим примером для понимания разницы было бы увидеть оба этих подхода к получению n-го числа фибоначчи. Отметьте этот материал из Массачусетского технологического института.


ИЗМЕНИТЬ


Разделить и победить подход Divide and Conquer approach

Подход к динамическому программированию enter image description here

Ответ 2

иногда, когда вы программируете рекурсивно, вы вызываете функцию с теми же параметрами несколько раз, что является ненужным.

Знаменитый пример чисел Фибоначчи:

           index: 1,2,3,4,5,6...
Fibonacci number: 1,1,2,3,5,8...

function F(n) {
    if (n < 3)
        return 1
    else
        return F(n-1) + F(n-2)
}

Пусть пробег F (5):

F(5) = F(4) + F(3)
     = {F(3)+F(2)} + {F(2)+F(1)}
     = {[F(2)+F(1)]+1} + {1+1}
     = 1+1+1+1+1

Итак, мы позвонили: 1 раз F (4) 2 раза F (3) 3 раза F (2) 2 раза F (1)

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

if (n==1 || n==2)
    return 1
else
    f1=1, f2=1
    for i=3 to n
         f = f1 + f2
         f1 = f2
         f2 = f

Позвольте снова называть F (5):

fibo1 = 1
fibo2 = 1 
fibo3 = (fibo1 + fibo2) = 1 + 1 = 2
fibo4 = (fibo2 + fibo3) = 1 + 2 = 3
fibo5 = (fibo3 + fibo4) = 2 + 3 = 5

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

Кстати, динамическое программирование не означает конвертировать рекурсивный код в итеративный код. Вы также можете сохранить подзапросы в переменную, если вам нужен рекурсивный код. В этом случае метод называется memoization. Для нашего примера это выглядит так:

// declare and initialize a dictionary
var dict = new Dictionary<int,int>();
for i=1 to n
    dict[i] = -1

function F(n) {
    if (n < 3)
        return 1
    else
    {
        if (dict[n] == -1)
            dict[n] = F(n-1) + F(n-2)

        return dict[n]                
    }
}

Таким образом, отношение к Divide и Conquer заключается в том, что алгоритмы D & D основаны на рекурсии. И некоторые версии из них имеют этот "вызов с несколькими функциями с той же проблемой параметров". Найдите "умножение матричной цепочки" и "самую длинную общую подпоследовательность" для таких примеров, где DP необходим для улучшения T (n) D & D algo.

Ответ 3

Другим различием между делением и покорением и динамическим программированием может быть:

Разделить и победить:

  • Работает ли над суб-проблемами и, следовательно, имеет больше времени.
  • В разделе "Разделить" и "подчинить" подзадачи не зависят друг от друга.

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

  • Решает проблемы только один раз, а затем сохраняет их в таблице.
  • В динамическом программировании подзадача не является независимой.

Ответ 4

Я предполагаю, что вы уже прочитали Википедию и другие учебные ресурсы по этому вопросу, поэтому я не буду перерабатывать какую-либо информацию. Я также должен предупредить, что я не специалист по компьютерной науке, но я поделюсь своими двумя центами на мое понимание этих тем...

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

Разбивает проблему на дискретные подзадачи. Рекурсивный алгоритм для последовательности Фибоначчи является примером динамического программирования, поскольку он решает для fib (n), сначала решая для fib (n-1). Чтобы решить исходную проблему, она решает другую проблему.

Разделить и покорить

Эти алгоритмы обычно решают подобные проблемы, а затем складывают их в конце. Mergesort - классический пример разделения и завоевания. Основное различие между этим примером и примером Фибоначчи заключается в том, что в объединенной системе разделение может (теоретически) быть произвольным, и независимо от того, как вы его разрезаете, вы все еще сходите и сортируете. Такой же объем работы должен быть выполнен для объединения массива, независимо от того, как вы его разделяете. Решение для fib (52) требует большего количества шагов, чем решение для fib (2).

Ответ 5

Я думаю о Divide & Conquer как рекурсивный подход и Dynamic Programming как заполнение таблицы.

Например, Merge Sort является алгоритмом Divide & Conquer, так как на каждом шаге вы разбиваете массив на две половины, рекурсивно вызываете Merge Sort на две половины и затем объединяете их.

Knapsack является алгоритмом Dynamic Programming при заполнении таблицы, представляющей оптимальные решения для подзадач общего рюкзака. Каждая запись в таблице соответствует максимальному значению, которое вы можете носить в сумке с весом w с учетом предметов 1-j.