Numérique et sciences informatiques (spécialité) · TerminaleBac
Programmation dynamique : exercices corrigés de Terminale NSI
Publié le 7 novembre 2026 · Mis à jour le 7 novembre 2026 · Signaler une erreur
L'essentiel
- La programmation dynamique découpe un problème en sous-problèmes, traite d'abord les plus petits puis monte vers les plus grands, et garde en mémoire chaque résultat obtenu 6.
- On commence par définir les sous-problèmes, puis par écrire la relation de récurrence, avant de choisir une version descendante ou ascendante 6.
- Le gain vient du fait qu'un même sous-problème n'est calculé qu'une seule fois, alors que la récursivité naïve le recalcule sans cesse 6.
- Les exercices vont du calcul d'un terme de la suite de Fibonacci jusqu'à la plus longue sous-chaîne commune, en passant par la monnaie et le sac à dos.
Comment utiliser ces exercices
Ces exercices te font pratiquer la programmation dynamique. Le principe : on découpe un problème en parties plus petites, on règle d'abord les plus petites, puis on monte vers les plus grandes, en gardant en mémoire ce qu'on a trouvé en chemin 6. Les exercices sont rangés par difficulté croissante : ceux de niveau 1 fixent le vocabulaire sur la suite de Fibonacci, ceux de niveau 2 demandent d'écrire une vraie récurrence, ceux de niveau 3 mélangent tableau à deux dimensions et raisonnement sur les indices.
Chaque exercice a un ou deux indices. Cherche d'abord seul pendant quelques minutes, sur papier, avant d'ouvrir un indice, puis compare avec la correction rédigée étape par étape.
Les exercices
Exercice 1 Combien d'appels pour le Fibonacci naïf ?
La suite de Fibonacci est définie par , et pour 6. On écrit la fonction récursive naïve :
def fib(n):
if n == 0 or n == 1:
return n
return fib(n - 1) + fib(n - 2)
On note le nombre total d'appels de la fonction fib (le premier compris) provoqués par l'appel fib(n).
- Donne et .
- Établis une relation entre , et .
- Calcule .
Indice 1
Pour , l'appel fib(n) compte pour 1, puis il déclenche fib(n - 1) et fib(n - 2).
Indice 2
Calcule les valeurs de , , dans l'ordre, comme dans un tableau.
Voir la correction pas à pas
Pour ou , la fonction renvoie directement : un seul appel, donc .
Pour , on compte l'appel lui-même, plus tous les appels déclenchés par
fib(n - 1), plus ceux déclenchés parfib(n - 2): .On calcule de proche en proche : .
.
.
.
Pour calculer seulement , la version naïve fait 15 appels. Ce nombre grossit très vite avec , car les mêmes sous-problèmes (fib(2), fib(3)…) sont recalculés de nombreuses fois : c'est le défaut de la méthode diviser pour régner quand les sous-problèmes se recoupent 6.
Exercice 2 Remplir un tableau de Fibonacci
On calcule en méthode ascendante, avec et 6.
- Écris la boucle Python qui remplit un tableau
Tde taille 11 des plus petits indices aux plus grands. - Remplis à la main le tableau pour les indices de 0 à 10.
- Quelle valeur renvoie le programme pour ?
Indice 1
Les deux premières cases sont les cas de base : T[0] = 0 et T[1] = 1.
Indice 2
Chaque case suivante est la somme des deux cases précédentes.
Voir la correction pas à pas
On initialise
T = [0] * 11, puisT[1] = 1.La boucle est
for i in range(2, 11): T[i] = T[i-1] + T[i-2].On remplit : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 pour les indices 0 à 10.
Le programme renvoie
T[10], soit 55.
Chaque case n'est calculée qu'une seule fois, à partir de cases déjà remplies. C'est le principe de la méthode ascendante : on avance dans l'ordre croissant et chaque résultat reste disponible pour les cases suivantes 6. Il suffit ici de 9 additions, alors que la version naïve de l'exercice 1 ferait 177 appels récursifs pour .
Exercice 3 Mémoïsation : compter les additions
On programme maintenant fib en version descendante avec un dictionnaire memo : avant tout calcul, on regarde si n est déjà dans memo ; sinon on calcule, on range le résultat dans memo, puis on le renvoie. Les cas n = 0 et n = 1 sont renvoyés directement, sans addition.
On appelle fib(8) avec un dictionnaire initialement vide. Combien d'additions le programme effectue-t-il au total ?
Indice 1
Une addition est faite chaque fois qu'une valeur avec est calculée pour la première fois.
Indice 2
Une valeur déjà présente dans memo est simplement relue, sans addition.
Voir la correction pas à pas
L'appel
fib(8)descend jusqu'àfib(1)etfib(0)en passant par toutes les valeurs intermédiaires.Les valeurs qui demandent une addition sont .
Chacune est calculée une seule fois, puis stockée dans
memo; les appels suivants la relisent sans calcul.Le nombre d'additions est donc le nombre d'indices de 2 à 8, soit .
La mémoïsation conserve les résultats déjà obtenus pour ne pas les refaire : on garde la structure récursive, mais chaque sous-problème n'est résolu qu'une fois. Le nombre d'additions est proportionnel à , alors que la version naïve explose.
Exercice 4 Monter un escalier
Léa monte un escalier de marches. À chaque pas, elle monte soit une marche, soit deux marches. On note le nombre de façons différentes d'atteindre le haut d'un escalier de marches.
- Donne et (on convient qu'il y a une seule façon de ne pas bouger).
- Justifie que pour .
- Calcule .
Indice 1
Regarde le tout dernier pas de Léa : de quelle marche vient-elle ?
Indice 2
Les valeurs ressemblent à une suite que tu connais déjà, décalée d'un cran.
Voir la correction pas à pas
Pour 0 marche, une seule façon (ne rien faire) : . Pour 1 marche, un seul pas simple : .
Pour , le dernier pas part soit de la marche (pas simple), soit de la marche (pas double). Ces deux cas sont distincts et couvrent tout.
Le nombre de façons d'arriver à la marche est , celui d'arriver à la marche est : on additionne, d'où la relation.
On calcule : , , , , .
Enfin .
Ici, le sous-problème est « atteindre la marche » et la récurrence découle d'un raisonnement sur le dernier pas. On retrouve la forme de la suite de Fibonacci 6 : . Reconnaître une récurrence connue fait gagner du temps, mais il faut toujours la justifier.
Exercice 5 Chemins dans une grille
Une grille compte 4 lignes et 5 colonnes de cases. Un jeton part de la case en haut à gauche et doit atteindre la case en bas à droite, en se déplaçant uniquement d'une case vers la droite ou d'une case vers le bas.
On note le nombre de chemins menant à la case de la ligne et de la colonne (numérotées à partir de 0).
- Donne et .
- Écris la relation de récurrence pour et .
- Combien y a-t-il de chemins jusqu'à la case d'arrivée ?
Indice 1
Pour entrer dans une case, on vient soit de la case au-dessus, soit de la case à gauche.
Indice 2
Remplis le tableau ligne par ligne : la première ligne et la première colonne ne contiennent que des 1.
Voir la correction pas à pas
Sur la première ligne, on ne peut arriver que par la gauche : un seul chemin, donc . De même .
Pour , on arrive d'en haut ou de la gauche : .
Ligne 1 : 1, 2, 3, 4, 5.
Ligne 2 : 1, 3, 6, 10, 15.
Ligne 3 : 1, 4, 10, 20, 35.
La case d'arrivée est .
Le tableau à deux dimensions est le réflexe de la méthode ascendante : chaque case dépend de cases déjà remplies, donc on les remplit dans l'ordre. Le nombre de cases à calculer est , bien moins que d'énumérer un par un les 35 chemins.
Exercice 6 Rendu de monnaie avec des pièces 1, 3 et 4
Un distributeur dispose de pièces de valeurs faciales 1, 3 et 4 en quantité illimitée. On cherche le nombre minimal de pièces pour rendre une somme . On note ce minimum, avec .
La version récursive s'appuie sur la remarque suivante : si l'on retire une pièce de valeur de la somme, il reste à rendre , ce qui donne mini = min(mini, 1 + dynRecursif(valeursFaciales, somme - x)) 2.
- Écris la relation de récurrence de .
- Calcule jusqu'à .
- Pour , compare avec la stratégie gloutonne qui prend toujours la plus grande pièce possible.
Indice 1
Pour , essaie chaque pièce et garde la meilleure option : .
Indice 2
La stratégie gloutonne pour 6 donne 4, puis 1, puis 1.
Voir la correction pas à pas
Relation : , avec .
.
.
.
.
.
: c'est 3 + 3.
Le glouton rend 4 + 1 + 1, soit 3 pièces : il n'est pas optimal.
Le minimum pour 6 est 2 pièces. Le glouton se trompe parce qu'un choix local (la plus grande pièce) n'est pas toujours compatible avec la meilleure solution globale. La programmation dynamique compare tous les choix possibles pour chaque sous-problème, ce qui rejoint le principe d'optimalité : une solution optimale se construit à partir de solutions optimales de sous-problèmes 6.
Exercice 7 Sac à dos : remplir le tableau
Dans le problème du sac à dos, on dispose de objets, chacun avec un poids et une valeur , et d'un sac de capacité limitée ; on cherche à maximiser la valeur emportée 4. Ce problème classique est NP-difficile, mais un algorithme de programmation dynamique le résout en temps pseudo-polynomial 6.
On considère quatre objets (poids ; valeur) : , , , , et un sac de capacité 7.
On note la valeur maximale avec les premiers objets et une capacité .
- Écris la relation de récurrence de et les cas de base.
- Calcule la valeur maximale pour la capacité 7.
- Quels objets choisit-on ?
Indice 1
Pour l'objet , deux choix : ne pas le prendre (), ou le prendre si ().
Indice 2
Tu peux aussi énumérer les parties de poids total au plus 7 pour vérifier ton tableau.
Voir la correction pas à pas
Cas de base : pour tout , et .
Récurrence : si , ; sinon .
Avec seul, pour à 7 : .
Avec et : vaut 0 pour , 3 pour , 4 pour et , 7 pour .
Avec , , : .
Avec aussi : .
Le maximum est 9. Il s'obtient avec et (poids , valeur ) ou avec et (poids , valeur ).
La valeur maximale est 9, obtenue de deux façons différentes. Le tableau contient cases pour objets et une capacité : son coût dépend de la valeur numérique de , ce qui explique le qualificatif « pseudo-polynomial » 6.
Exercice 8 Plus longue sous-chaîne commune
Étant donné deux textes et , on cherche une plus longue sous-chaîne commune, problème que l'on peut traiter par la programmation dynamique 2. Dans cet exercice, une sous-chaîne est une suite de lettres consécutives dans le texte.
On prend et . On note la longueur de la plus longue sous-chaîne commune qui se termine à la lettre de et à la lettre de (les lettres sont numérotées à partir de 1).
- Écris la relation de récurrence de et le cas de base.
- Explique comment lire la réponse dans le tableau.
- Détermine la longueur de la plus longue sous-chaîne commune et donne-la.
Indice 1
Si les lettres et sont différentes, aucune sous-chaîne commune ne peut se terminer ici.
Indice 2
Si elles sont égales, on prolonge la sous-chaîne qui se terminait juste avant, aux positions et .
Voir la correction pas à pas
Cas de base : (texte vide).
Si , alors ; sinon .
La réponse n'est pas forcément dans la dernière case : une sous-chaîne peut se terminer n'importe où, donc on prend le maximum de toutes les cases.
Dans , les lettres F, O, R, M se suivent aux positions 3 à 6 ; dans , elles occupent les positions 1 à 4.
Les valeurs de sur cette diagonale sont , , , .
Après M, continue par A et par U : . Les autres diagonales restent bien plus courtes, car le reste de (ULE) ne partage avec que des lettres isolées.
La plus longue sous-chaîne commune est « FORM », de longueur 4.
Ici encore, le sous-problème est défini par deux indices, ce qui donne un tableau à deux dimensions. Le piège est le travail sur les indices, souvent plus délicat que l'idée de la récurrence elle-même 2. Retiens que, pour des lettres consécutives, la case retombe à 0 en cas de différence, et que la réponse est le maximum du tableau.
Les questions qu'on se pose
Comment savoir si un problème relève de la programmation dynamique ?
Cherche deux signes : le problème se décompose en sous-problèmes plus petits, et ces sous-problèmes se recoupent (on retomberait plusieurs fois sur le même). Si les sous-problèmes sont indépendants, la méthode diviser pour régner suffit 6. Un autre signe est le principe d'optimalité : la solution optimale se construit en combinant des solutions optimales de sous-problèmes 6. Pour un problème d'optimisation (minimum, maximum) dont les sous-problèmes se recoupent, pense à cette méthode.
Quelle différence entre version ascendante et version descendante ?
Dans la version ascendante, tu remplis un tableau des plus petits sous-problèmes vers les plus grands, avec une boucle. Dans la version descendante, tu écris la fonction récursive et tu mémorises chaque résultat pour ne pas le recalculer (mémoïsation) 6. Les deux calculent chaque sous-problème une seule fois. La première évite la récursivité et ses limites de profondeur ; la seconde est souvent plus proche de la formule de récurrence.
Que faut-il écrire sur la copie au bac pour une question de programmation dynamique ?
Écris dans cet ordre : ce que représente chaque case du tableau (le sous-problème), la relation de récurrence, les cas de base, le sens de remplissage, puis la case qui contient la réponse. Une récurrence correcte sans cas de base ou sans définition du sous-problème perd facilement des points. Termine par le calcul effectif du tableau, rempli ligne par ligne.
Sources
Programme visé : Programme de l'enseignement de spécialité de numérique et sciences informatiques de la classe terminale de la voie générale · Bulletin officiel de l'Éducation nationale
- Programme de l'enseignement de spécialité de numérique et sciences informatiques de la classe terminale de la voie générale, Bulletin officiel de l'Éducation nationale. Consulté le 7 novembre 2026.
- Ressource Éduscol - Programmation dynamique (Terminale NSI), eduscol.education.gouv.fr. Consulté le 7 novembre 2026.
- Programmes et ressources en numérique et sciences informatiques - voie générale, eduscol.education.gouv.fr. Consulté le 7 novembre 2026.
- Recherche Opérationnelle - Programmation Dynamique, CNRS (Université Lyon). Consulté le 7 novembre 2026.
- Programmation dynamique et mémoïsation, CNRS. Consulté le 7 novembre 2026.
- Programmation dynamique, Wikipédia. Consulté le 7 novembre 2026.
Les numéros dans le texte renvoient à ces sources. Une source qui ne dit pas ce qu'on lui fait dire ? Signale-le.