Adloun

Chemins de valeur optimale

Cours · algorithmique (école d'ingénieur), chapitre 5 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun

Objectifs du chapitre

  • Reconnaître un problème de chemin optimal : une suite de déplacements élémentaires, chacun avec un coût ou une valeur.
  • Écrire la récurrence en regardant le dernier déplacement, d'abord sur une ligne de villes, puis sur une grille.
  • Traiter proprement les cas particuliers (bords de la grille, cases inaccessibles) et choisir un ordre de calcul.

Au chapitre 1, Zébulon cherchait un chemin de valeur maximum en sautant de case en case. Ce chapitre généralise cette situation : des villes reliées par des lignes de bus, puis un robot qui se déplace sur une grille. Dans tous les cas, la question clé est la même : d'où vient-on, au dernier pas ?

5.1 Deux lignes de bus

Les villes sont alignées et desservies par deux lignes de bus. Depuis la ville on peut aller :

On veut un trajet de coût minimum de la ville à la ville .

Exemple 5.1cinq villes

et (les cases marquées n'ont pas de sens : il n'y a pas de ville ou ). Le trajet coûte .

Supposons le problème résolu

Notons le coût minimum d'un trajet de la ville à la ville . Un trajet optimal vers (avec ) arrive par l'un des deux derniers trajets possibles :

Proposition 5.2Récurrence des deux lignes de bus

Base. ;   .

Hérédité. :

On calcule par croissants, en :


static int[] calculerM(int[] D1, int[] D2) { int n = D1.length;
    // retourne M[0:n] de terme général M[j] = m(j)
    int[] M = new int[n];
    M[0] = 0;                                 // base
    if (n > 1) M[1] = D1[0];                  // base
    for (int j = 2; j < n; j++)               // hérédité, par j croissants
        M[j] = Math.min(M[j-1] + D1[j-1], M[j-2] + D2[j-2]);
    return M;
}

Pour afficher le trajet, on n'a pas mémorisé d'arguments : on retrouve le dernier trajet en testant laquelle des deux égalités est vérifiée. Notons un trajet de coût minimum de à : si , et sinon.


static void afficherCheminMinimum(int[] M, int[] D1, int[] D2, int j) {
    // affiche tr(j). Appel principal : afficherCheminMinimum(M, D1, D2, n-1)
    if (j == 0) { System.out.print("0"); return; }  // tr(0) a été affiché
    if (M[j] == M[j-1] + D1[j-1]) {  // dernier trajet : j-1 -> j
        afficherCheminMinimum(M, D1, D2, j-1);  // tr(j-1) a été affiché
        System.out.printf("--(%d)-->%d", D1[j-1], j);
    } else {  // dernier trajet : j-2 -> j
        afficherCheminMinimum(M, D1, D2, j-2);  // tr(j-2) a été affiché
        System.out.printf("--(%d)-->%d", D2[j-2], j);
    }  // donc tr(j) a été affiché
}

$ java BusDeuxLignes
M = [0, 10, 30, 60, 90]
Coût minimum m(4) = 90 : 0--(10)-->1--(50)-->3--(30)-->4

Attention

L'appel avec est correct : , donc on passe par la première branche et l'on ne consulte jamais . Vérifiez toujours, pour une fonction d'affichage, que les petits cas ne provoquent pas d'accès hors du tableau.

Ici le minimum est atteint deux fois pour : et . Il y a deux trajets optimaux ; la fonction affiche celui qu'elle teste en premier.

La suite du cours est sur Adloun

Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.

Lire la suite du cours

En accès libre, sans inscription.

Exercices corrigés de ce chapitre

Lire la suite du cours →