Adloun

informatique (MP2I/MPI) · Chapitre 17 · Exercice de TD

Le sens d'une boucle décide du problème résolu

Programmation dynamique · niveau 2

Énoncé

On veut économiser la mémoire du sac à dos en n'utilisant qu'une seule ligne. Ces deux fragments diffèrent d'un seul caractère. Que calcule chacun ?


/* (A) */  for (int i = 0; i < n; i++)
               for (int c = C; c >= p[i]; c--)
                   if (v[i] + m[c - p[i]] > m[c]) { m[c] = v[i] + m[c - p[i]]; }

/* (B) */  for (int i = 0; i < n; i++)
               for (int c = p[i]; c <= C; c++)
                   if (v[i] + m[c - p[i]] > m[c]) { m[c] = v[i] + m[c - p[i]]; }

Corrigé

(A) résout le sac à dos du chapitre (chaque objet au plus une fois). (B) résout le sac à dos illimité, où chaque objet peut être pris autant de fois qu'on veut. Et rien, dans le code, ne le dit.

Pourquoi. La ligne tient à la fois l'ancienne ligne et la nouvelle . Quand on lit m[c - p[i]] :

  • en décroissant, la case est à gauche de , donc pas encore réécrite pendant ce tour : elle contient . C'est bien la récurrence du chapitre, qui interdit de reprendre l'objet .
  • en croissant, la case a déjà été mise à jour pendant ce tour : elle contient , donc une valeur qui a peut-être déjà pris l'objet . On l'autorise à le reprendre.

Mesure, avec deux objets , :


C=4   (A) decroissant = 4    (B) croissant = 6
C=5   (A) decroissant = 7    (B) croissant = 7
C=6   (A) decroissant = 7    (B) croissant = 9
C=7   (A) decroissant = 7    (B) croissant = 10

À , (A) rend (les deux objets, poids ) et (B) rend (trois fois l'objet de poids ). À les deux coïncident, ce qui est le pire cas pour le testeur : un jeu de tests limité à n'aurait rien vu. Le chapitre chap:discipline le dit autrement : on teste aux frontières, et ici la frontière est la capacité où reprendre un objet devient possible.

À retenir. Une réduction de mémoire n'est jamais neutre. Ici elle ne change pas la complexité en temps, mais elle rend le sens de la boucle sémantique : la même ligne de code résout deux problèmes différents selon un signe. Quand on écrase la table, on écrit l'ordre de parcours dans un commentaire, au-dessus de la boucle.

Exercices semblables

Le cours du chapitre · Tous les exercices du chapitre