algorithmique (école d'ingénieur) · Chapitre 7 · Application directe du cours
Réseau de bus : trajet de coût minimum
Graphes sans circuit et ordonnancement de projets · niveau 2
Énoncé
On reprend le réseau de l'exercice 7.2. Une ligne directe de à n'existe que si ; elle coûte , rangé dans C[i][j] ( s'il n'y a pas de ligne) :
On note le coût minimum d'un trajet de la ville à la ville , et l'ensemble des villes qui envoient un arc sur .
- Donner l'équation de récurrence des valeurs : base et hérédité, avec l'intervalle des valeurs de .
- Pourquoi peut-on calculer les par croissants ?
- Écrire
int[][] calculerMA(Liste[] Gp, int[][] C)qui retourne de terme général et de terme général , la ville qui précède sur un trajet optimal (on pose ). Le paramètreGpest le graphe symétrique. - Écrire
void acm(int[] A, int[][] C, int j)qui affiche un trajet de coût minimum de à , sous la forme0--(5)-->1--(20)-->4. - Donner , et les trajets optimaux vers et vers .
Corrigé
- Supposons le problème résolu : un trajet optimal vers arrive sur par une dernière ligne , avec , et sa partie de à est elle-même optimale (principe d'optimalité). D'où :
Si est vide, le minimum vaut : est inaccessible.
- Tous les prédécesseurs de ont un numéro (les lignes vont de à , la numérotation est isotone) : quand on calcule par croissants, toutes les valeurs utiles sont connues.
- On parcourt les prédécesseurs dans le graphe symétrique et l'on mémorise l'argument du minimum.
static final int INFINI = Integer.MAX_VALUE / 2;
static int[][] calculerMA(Liste[] Gp, int[][] C) { int n = Gp.length;
int[] M = new int[n], A = new int[n];
M[0] = 0; A[0] = -1; // base
for (int j = 1; j < n; j++) { // par j croissants
M[j] = INFINI; A[j] = -1;
for (Liste l = Gp[j]; !vide(l); l = reste(l)) { int i = premier(l);
if (M[i] + C[i][j] < M[j]) { // meilleur trajet arrivant par i
M[j] = M[i] + C[i][j]; A[j] = i;
}
}
} // M[j] = m(j), A[j] = a(j)
return new int[][] {M, A};
}
La valeur est Integer.MAX_VALUE / 2, pour que ne dépasse pas la capacité des int. Chaque sommet et chaque arc est touché une fois : .
- On affiche d'abord le trajet jusqu'à , puis la dernière ligne :
static void acm(int[] A, int[][] C, int j) {
if (j == 0) { System.out.print("0"); return; } // trajet réduit à 0 : affiché
acm(A, C, A[j]); // trajet de 0 à a(j) affiché
System.out.printf("--(%d)-->%d", C[A[j]][j], j); // puis la ligne a(j) --> j
}
- Exécution :
M = [0, 5, 10, 20, 25], A = [-1, 0, 1, 2, 1]
0--(5)-->1--(20)-->4
0--(5)-->1--(5)-->2--(10)-->3
nom : M
valeurs : 0 5 10 20 25
vert : 0 1 4
fleches : 0->1 1->2 2->3 1->4
legende : flèches de a(j) vers j ; en vert : le trajet 0, 1, 4 (coût 25)
Vers , le trajet direct () est battu par () ; vers , la ligne directe () est à égalité avec : l'inégalité stricte garde le premier prédécesseur examiné.
100 % gratuit
La suite du chapitre est sur Adloun
- 11 autres exercices corrigés dans ce chapitre
- Les 2 QCM du chapitre, le premier sans compte
- Le podcast et la vidéo du chapitre : 2 minutes d'écoute sans compte
- Le tuteur, qui guide pas à pas sans donner la réponse
Sans compte : le cours, le premier QCM et 2 minutes de podcast et de vidéo. Exercices et tuteur : inscription gratuite en 30 secondes, sans carte bancaire.