Diviser et conquérir
Divide and Conquer fonctionne en divisant le problème en sous-problèmes, conquérir chaque sous-problème de manière récursive et combiner ces solutions.
Programmation dynamique
La programmation dynamique est une technique pour résoudre des problèmes avec des sous-problèmes qui se chevauchent. Chaque sous-problème est résolu une seule fois et le résultat de chaque sous-problème est stocké dans une table (généralement implémentée sous forme de tableau ou de table de hachage) pour des références futures. Ces sous-solutions peuvent être utilisées pour obtenir la solution originale et la technique de stockage des solutions de sous-problème est connue sous le nom de mémorisation.
Vous pouvez penser à DP = recursion + re-use
Un exemple classique pour comprendre la différence serait de voir ces deux approches pour obtenir le nième nombre de fibonacci. Vérifiez ce matériel du MIT.
Approche Divide and Conquer
Approche de programmation dynamique
L'autre différence entre diviser pour conquérir et la programmation dynamique pourrait être:
Diviser et conquérir:
Programmation dynamique:
la source
parfois lors de la programmation récursive, vous appelez la fonction avec les mêmes paramètres plusieurs fois, ce qui n'est pas habituel.
Le fameux exemple de nombres de Fibonacci:
Lançons F (5):
Nous avons donc appelé: 1 fois F (4) 2 fois F (3) 3 fois F (2) 2 fois F (1)
Approche de programmation dynamique: si vous appelez une fonction avec le même paramètre plus d'une fois, enregistrez le résultat dans une variable pour y accéder directement la prochaine fois. La manière itérative:
Appelons à nouveau F (5):
Comme vous pouvez le voir, chaque fois que vous avez besoin de l'appel multiple, vous accédez simplement à la variable correspondante pour obtenir la valeur au lieu de la recalculer.
À propos, la programmation dynamique ne signifie pas convertir un code récursif en code itératif. Vous pouvez également enregistrer les sous-résultats dans une variable si vous souhaitez un code récursif. Dans ce cas, la technique s'appelle la mémorisation. Pour notre exemple, cela ressemble à ceci:
Donc, la relation avec Divide and Conquer est que les algorithmes de D&D reposent sur la récursivité. Et certaines versions d'entre eux ont cet «appel de fonctions multiples avec le même problème de paramètre». Recherchez «multiplication de chaîne matricielle» et «sous-séquence commune la plus longue» pour de tels exemples où DP est nécessaire pour améliorer le T (n) de l'algo D&D.
la source
Programmation dynamique et similitudes diviser-pour-conquérir
Comme je le vois pour le moment, je peux dire que la programmation dynamique est une extension du paradigme diviser pour conquérir .
Je ne les traiterais pas comme quelque chose de complètement différent. Parce qu'ils fonctionnent tous les deux en décomposant récursivement un problème en deux ou plusieurs sous-problèmes du même type ou d'un type apparenté, jusqu'à ce que ceux-ci deviennent suffisamment simples pour être résolus directement. Les solutions aux sous-problèmes sont ensuite combinées pour donner une solution au problème d'origine.
Alors pourquoi avons-nous encore des noms de paradigme différents alors et pourquoi j'ai appelé la programmation dynamique une extension. C'est parce que l'approche de programmation dynamique peut être appliquée au problème uniquement si le problème comporte certaines restrictions ou conditions préalables . Et après cette programmation dynamique étend l'approche diviser pour conquérir avec la technique de mémorisation ou de tabulation .
Allons-y étape par étape…
Conditions préalables / restrictions de programmation dynamique
Comme nous venons de le découvrir, il y a deux attributs clés que le problème de division et de conquête doit avoir pour que la programmation dynamique soit applicable:
Sous-structure optimale - une solution optimale peut être construite à partir de solutions optimales de ses sous-problèmes
Chevauchement des sous-problèmes - le problème peut être décomposé en sous-problèmes qui sont réutilisés plusieurs fois ou un algorithme récursif pour le problème résout le même sous-problème à plusieurs reprises plutôt que de toujours générer de nouveaux sous-problèmes
Une fois ces deux conditions remplies, nous pouvons dire que ce problème de division pour vaincre peut être résolu en utilisant une approche de programmation dynamique.
Extension de programmation dynamique pour Divide and Conquer
L'approche de programmation dynamique étend l'approche de division pour conquérir avec deux techniques ( mémorisation et tabulation ) qui ont toutes deux pour but de stocker et de réutiliser des solutions de sous-problèmes susceptibles d'améliorer considérablement les performances. Par exemple, l'implémentation récursive naïve de la fonction de Fibonacci a une complexité temporelle
O(2^n)
où la solution DP fait la même chose avec seulement leO(n)
temps.La mémorisation (remplissage du cache de haut en bas) fait référence à la technique de mise en cache et de réutilisation des résultats précédemment calculés. La
fib
fonction mémorisée ressemblerait donc à ceci:La tabulation (remplissage du cache de bas en haut) est similaire mais se concentre sur le remplissage des entrées du cache. Le calcul des valeurs dans le cache est plus simple de manière itérative. La version tabulation de
fib
ressemblerait à ceci:Vous pouvez en savoir plus sur la mémorisation et la comparaison des tableaux ici .
L'idée principale que vous devez comprendre ici est que, parce que notre problème de division et de conquête a des sous-problèmes qui se chevauchent, la mise en cache des solutions de sous-problèmes devient possible et ainsi la mémorisation / tabulation entre en scène.
Alors, quelle est la différence entre DP et DC après tout
Puisque nous connaissons maintenant les prérequis DP et ses méthodologies, nous sommes prêts à rassembler tout ce qui a été mentionné ci-dessus en une seule image.
Si vous souhaitez voir des exemples de code, vous pouvez consulter des explications plus détaillées ici où vous trouverez deux exemples d'algorithmes: la recherche binaire et la distance minimale d'édition (distance de Levenshtein) qui illustrent la différence entre DP et DC.
la source
Je suppose que vous avez déjà lu Wikipédia et d'autres ressources académiques à ce sujet, je ne recyclerai donc aucune de ces informations. Je dois également souligner que je ne suis en aucun cas un expert en informatique, mais je vais partager mes deux cents sur ma compréhension de ces sujets ...
Programmation dynamique
Décompose le problème en sous-problèmes discrets. L'algorithme récursif pour la séquence de Fibonacci est un exemple de programmation dynamique, car il résout pour fib (n) en résolvant d'abord pour fib (n-1). Afin de résoudre le problème d'origine, il résout un autre problème .
Diviser et conquérir
Ces algorithmes résolvent généralement des éléments similaires du problème, puis les rassemblent à la fin. Mergesort est un exemple classique de division et de conquête. La principale différence entre cet exemple et l'exemple de Fibonacci est que dans un tri de fusion, la division peut (théoriquement) être arbitraire, et quelle que soit la façon dont vous la découpez, vous fusionnez et triez toujours. La même quantité de travail doit être effectuée pour fusionner le tableau, quelle que soit la façon dont vous le divisez. La résolution de fib (52) nécessite plus d'étapes que la résolution de fib (2).
la source
Je pense
Divide & Conquer
à une approche récursive etDynamic Programming
à un remplissage de tableau.Par exemple,
Merge Sort
est unDivide & Conquer
algorithme, comme à chaque étape, vous divisez le tableau en deux moitiés, appelez récursivementMerge Sort
les deux moitiés, puis fusionnez-les.Knapsack
est unDynamic Programming
algorithme lorsque vous remplissez un tableau représentant des solutions optimales aux sous-problèmes du sac à dos global. Chaque entrée du tableau correspond à la valeur maximale que vous pouvez transporter dans un sac de poids w en fonction des articles 1-j.la source
Divide and Conquer comporte trois étapes à chaque niveau de récursivité:
La programmation dynamique comprend les quatre étapes suivantes:
1. Caractériser la structure des solutions optimales.
2. Définissez récursivement les valeurs des solutions optimales.
3. Calculez la valeur des solutions optimales.
4. Construisez une solution optimale à partir d'informations calculées .
Pour une compréhension plus facile, voyons diviser et conquérir comme une solution de force brute et son optimisation en tant que programmation dynamique.
NB Les algorithmes de division et de conquête avec des sous-problèmes qui se chevauchent ne peuvent être optimisés qu'avec dp.
la source
Comme nous pouvons le voir ci-dessus, aucun fait (x) n'est répété donc factoriel a des problèmes non chevauchants.
Comme nous pouvons le voir ci-dessus, fib (4) et fib (3) utilisent tous deux fib (2). de même, tant de fib (x) se répètent. c'est pourquoi Fibonacci a des sous-problèmes qui se chevauchent.
la source