Décider des sous-problèmes pour la programmation dynamique

39

J'ai utilisé la technique de la programmation dynamique à plusieurs reprises, mais aujourd'hui, un ami m'a demandé comment je définissais mes sous-problèmes. Je me suis rendu compte que je n'avais aucun moyen de fournir une réponse formelle objective. Comment définissez-vous formellement un sous-problème pour un problème que vous voudriez résoudre en utilisant la programmation dynamique?

Daniel Gratzer
la source
Il semble qu'aucune des réponses existantes (avril 2019) ne soit suffisante, en particulier pour les débutants. Je recommanderais des tutoriels sur d'autres sites.
Apass.Jack

Réponses:

35

Le principe de la programmation dynamique est de penser de haut en bas (c'est-à-dire de manière récursive) tout en résolvant de bas en haut. Une bonne stratégie pour concevoir un PDD consiste donc à formuler le problème de manière récursive et à générer ainsi des sous-problèmes.

Suresh
la source
14
Je prétends que c'est la seule stratégie.
JeffE
2
@JeffE Oui, j'ai lu et utilisé vos notes lorsque j'enseignais des cours d'algorithme et c'était efficace. Citation: "La dynamique ne consiste pas à remplir des tableaux. Il s'agit d'une récursion intelligente!"
Dai
2
Ma compréhension de la manière d'enseigner aux DP est fortement influencée par les notes de @ JeffE :)
Suresh
3
Il est également possible de transformer automatiquement une procédure récursive de haut en bas en un algorithme de programmation dynamique. Lorsque vous êtes sur le point de revenir, stockez la réponse dans une table de hachage. Au début de chaque appel, vérifiez si la réponse est déjà dans la table de hachage et, le cas échéant, renvoyez-la immédiatement. De nombreux algorithmes deviennent faciles avec cette idée. Par exemple, avec un tel tableau, les algorithmes récursifs sur les essais fonctionnent automatiquement sur les DAWG. En stockant une valeur sentinelle dans la table au début d'un appel, les mêmes algorithmes peuvent fonctionner même sur des DFA. Les algorithmes sur les BDD deviennent très faciles à spécifier récursivement.
Jules
1
Enfin, cela peut avoir d’énormes avantages en termes de performances. Par exemple, l’algorithme traditionnel de somme de sous-ensembles ascendante peut calculer des tonnes d’entrées de table inutiles. Avec cette méthode, seules les entrées de table nécessaires seront calculées.
Jules
4

Comme @Suresh l'a fait remarquer, une fois que vous savez que votre problème peut être résolu par DP (c'est-à-dire qu'il présente une sous-structure optimale et des sous-problèmes qui se chevauchent), vous pouvez penser à une solution récursive de division et de conquête.

Bien sûr, diviser pour régner sera extrêmement inefficace, car chaque sous-problème rencontré dans l’arbre de récursion associé sera résolu à nouveau, même s’il a déjà été trouvé et résolu. C'est là que DP diffère: chaque fois que vous rencontrez un sous-problème, vous le résolvez et stockez sa solution dans un tableau. Plus tard, lorsque vous rencontrez à nouveau ce sous-problème, vous accédez en temps sa solution au lieu de la résoudre à nouveau. Étant donné que le nombre de sous-problèmes qui se chevauchent est généralement limité par un polynôme et que le temps nécessaire pour résoudre un sous-problème est également polynomial (sinon, DP ne peut pas fournir une solution rentable), vous obtenez généralement une solution polynomiale.O(1)

Par conséquent, le fait de penser à une solution de division et de conquête vous donnera une idée de ce qu’est un sous-problème pour votre problème particulier.

Massimo Cafaro
la source
1
Une "sous-structure optimale" (peu importe ce que cela signifie) n'est probablement pas une condition suffisante pour la solvabilité de DP. Le "chevauchement de sous-problèmes" n’est certainement pas nécessaire.
Raphaël
1
La sous-structure optimale et les problèmes qui se chevauchent se manifestent tous deux par des problèmes pouvant être résolus efficacement par le DP. Bien entendu, une infrastructure optimale ne suffit pas, à elle seule, à la résolubilité du DP. Cependant, si vous n'avez pas de sous-problèmes qui se chevauchent, vous pouvez alors résoudre le problème en divisant pour régner avec le même coût: en effet, l'avantage de DP sur diviser une conquête est que chaque sous-problème est résolu exactement une fois lorsqu'il est rencontré dans l'arbre de récursivité. .
Massimo Cafaro
1
Ce n'est pas ma formulation: vous la trouverez dans "Introduction aux algorithmes" de Cormen, Leiserson, Rivest et Stein et dans de nombreux autres manuels sur les algorithmes.
Massimo Cafaro
1
Jup, et la plupart ont au moins partiellement tort. Je suis heureux de développer si vous posez une question appropriée.
Raphaël
1
Je ne suis pas sûr de bien comprendre votre dernier commentaire. Pour montrer que ce type de caractérisation est erroné (il ne peut pas être en partie erroné: il est correct ou incorrect), vous pouvez simplement montrer, en contre-exemple, un problème qui ne présente pas à la fois une sous-structure optimale et des sous-problèmes qui se chevauchent. se prêtant à une solution DP polynomiale. Mais notons que, dans ce contexte, cela signifie une solution qui est manifestement meilleure que la division et la conquête ordinaires.
Massimo Cafaro
2

Mon expérience est de trouver un moyen de "réduire l'énumération redondante à l'aide de la sauvegarde de la valeur utile déjà énumérée". À propos, la programmation dynamique est très populaire dans le concours international de programmation collégiale ICPC. Tout le monde peut avoir son propre sentiment à propos de DP après la pratique de plusieurs problèmes de CIPC.

Peng Zhang
la source