Qu'est-ce que Programmation dynamique ?
Méthode de conception d'algorithmes qui découpe un problème en sous-problèmes plus petits et enregistre leurs réponses dans une table pour les réutiliser, ce qui évite de recalculer plusieurs fois la même chose. On l'utilise pour le problème du sac à dos, le rendu de monnaie avec un minimum de pièces, la plus longue sous-séquence commune, les plus courts chemins, etc.
Nom japonais: 動的計画法
« Programmation dynamique » apparaît dans 3 questions d'entraînement réparties sur 1 thèmes, dont Structures de données et algorithmes.
Domaine: Structures de données et algorithmes
Mémoïsation et remplissage de tables
Il existe deux façons de l'implémenter : la mémoïsation (descendante), qui garde la récursion mais retient les résultats calculés, et l'approche ascendante, qui remplit une table en partant des plus petits sous-problèmes. Pour le problème du sac à dos 0/1, par exemple, la table contient « la valeur maximale atteignable avec les objets jusqu'à i dans la capacité c », et on la remplit en prenant le plus grand des deux cas, avec ou sans chaque objet. Pour n objets et une capacité W, cela prend O(nW). Le problème du nombre minimal de pièces se résout de même en tabulant le nombre minimal de pièces pour chaque montant de 0 jusqu'à la cible.
Différence avec les algorithmes gloutons, et applications
Un algorithme glouton se contente de prendre le choix qui paraît le meilleur à chaque instant et de passer à la suite : il est rapide, mais pas optimal pour certains problèmes. Pour payer 8 yens avec des pièces de 1, 4 et 6 yens, l'algorithme glouton utilise trois pièces, 6 + 1 + 1, alors que la programmation dynamique en trouve deux, 4 + 4. La programmation dynamique est très utilisée, par exemple pour la distance d'édition et la plus longue sous-séquence commune de chaînes de caractères (comme dans la commande diff), l'alignement de séquences d'ADN, l'algorithme de Viterbi en reconnaissance vocale et l'algorithme de Floyd-Warshall pour les plus courts chemins entre toutes les paires de sommets.
Questions fréquentes
En quoi la programmation dynamique diffère-t-elle de « diviser pour régner » ?
Les deux découpent un problème en sous-problèmes, mais dans les algorithmes de type « diviser pour régner » comme le tri fusion, les sous-problèmes ne se chevauchent pas, si bien qu'il n'est pas nécessaire d'enregistrer les réponses. La programmation dynamique s'en distingue en enregistrant et en réutilisant les réponses quand les mêmes sous-problèmes apparaissent de nombreuses fois.
Quelles sont les faiblesses de la programmation dynamique ?
Elle demande une mémoire et un travail proportionnels à la taille de la table. Le O(nW) du problème du sac à dos est proportionnel à la valeur de la capacité W, si bien qu'il devient impraticable quand W est très grand. On peut réduire la mémoire en n'enregistrant que le nécessaire ou en ne gardant que la ligne précédente de la table.