Les algorithmes gloutons⚓︎
Fiche méthode & révision — Première NSI · Chapitre 14
Fiche compacte pour refaire seul les exercices : principe glouton, rendu de monnaie, sac à dos, stations-service et TSP (plus proche voisin).
1. Objectifs⚓︎
À la fin du chapitre, vous devez savoir :
- connaître le principe d'un algorithme glouton ;
- expliquer choix local, optimum local / global, optimalité non garantie ;
- dérouler les algorithmes (monnaie, sac, stations, TSP) ;
- comparer glouton et force brute, fournir un contre-exemple ;
- choisir une heuristique (valeur, poids, ratio) et connaître ses limites ;
- évaluer le coût d'un glouton (tri compris) ;
- programmer et justifier terminaison et correction.
2. Définitions essentielles⚓︎
| Terme | Définition |
|---|---|
| Problème d'optimisation | Chercher la meilleure solution sous contraintes. |
| Algorithme glouton | Fait à chaque étape le meilleur choix immédiat. |
| Choix local | Décision prise sans voir la suite. |
| Optimum local / global | Meilleur proche / meilleur absolu. |
| Force brute | Teste toutes les possibilités. |
| Contrainte | Condition à respecter (capacité, autonomie…). |
| Solution réalisable | Respecte les contraintes. |
| Solution optimale | La meilleure réalisable. |
| Ratio valeur/poids | Critère du sac à dos. |
| Distancier | Tableau des distances entre villes. |
| Correction partielle | Si l'algo s'arrête, le résultat est valide. |
| Terminaison | L'algo s'arrête toujours. |
| Correction totale | Partielle + terminaison. |
| Heuristique | Critère de choix glouton (valeur, poids, ratio…). |
| Système canonique | Système de pièces où le glouton est toujours optimal (ex : euro). |
| Système non canonique | Système où le glouton est parfois non optimal (ex : {1,3,4}). |
| Sac 0/1 | Objets indivisibles : on prend tout l'objet ou rien (notre cas). |
| Sac fractionnaire | Objets sécables : le glouton par ratio y est optimal. |
| Variant | Quantité entière ≥ 0 qui décroît → prouve la terminaison. |
| Invariant | Propriété préservée à chaque tour → prouve la correction partielle. |
3. Force brute vs glouton⚓︎
| Force brute | Glouton | |
|---|---|---|
| Principe | explore les possibilités | choix immédiat |
| Coût | élevé | faible (rapide) |
| Retour en arrière | oui | non |
| Optimum | peut le trouver | non garanti |
4. Rendu de monnaie⚓︎
Étapes
- trier les pièces par ordre décroissant ;
- initialiser une liste de compteurs ;
- parcourir les pièces ;
- prendre une pièce tant qu'elle ne dépasse pas la somme restante ;
- diminuer la somme ;
- augmenter le compteur ;
- vérifier que le reste final vaut 0 ;
- compter les pièces pour juger la qualité.
def rendu(somme, pieces): # pieces triées décroissant
choisies = [0] * len(pieces)
for i in range(len(pieces)):
while pieces[i] <= somme:
somme = somme - pieces[i]
choisies[i] += 1
return choisies # le reste 'somme' doit valoir 0
somme: reste à rendre ;pieces: liste triée ;i: indice courant ;choisies: compteurs par pièce.
Comparaisons
- Système européen : le glouton donne toujours l'optimum.
{4, 3, 1}pour 6 : glouton4 + 1 + 1(3 pièces) ; optimal3 + 3(2 pièces) → glouton non optimal.{10, 5, 2}pour 31 : glouton prend10 + 10 + 10, reste1→ bloqué (échec), alors qu'une solution existe (10 + 10 + 5 + 2 + 2 + 2).
5. Tester l'optimalité⚓︎
Méthode
- calculer la solution gloutonne ;
- chercher une autre combinaison sur un petit exemple ;
- comparer (nombre de pièces / valeur totale) ;
- si le glouton est moins bon → fournir un contre-exemple.
Trois situations à distinguer
- résultat valide (réalisable) ;
- résultat optimal (le meilleur) ;
- problème sans solution (le glouton se bloque).
6. Sac à dos simple⚓︎
Étapes
Identifier valeur, poids, capacité → trier selon le critère → parcourir → prendre si le poids rentre → enregistrer → renvoyer les objets choisis.
def sac_simple(objets, capacite): # objets = [(nom, poids), ...]
poids_total = 0
choisis = []
for nom, poids in objets:
if poids_total + poids <= capacite:
choisis.append(nom)
poids_total += poids
return choisis
7. Sac à dos avec dictionnaire⚓︎
pris = {}
for nom, poids in objets:
if poids_total + poids <= capacite:
pris[nom] = 1 # ajout d'une paire clé-valeur
poids_total += poids
pris[nom] = 1ajoute la pairenom: 1(objet sélectionné).
8. Sac à dos avec ratio⚓︎
Étapes
- calculer
valeur / poids; - ajouter le ratio aux données de chaque objet ;
- trier par ratio décroissant ;
- parcourir la liste triée ;
- ajouter les objets compatibles ;
- calculer masse et valeur totales.
# objets triés par ratio décroissant : [(nom, valeur, poids, ratio), ...]
masse = 0
valeur_totale = 0
for nom, valeur, poids, ratio in objets_tries:
if masse + poids <= capacite:
masse += poids
valeur_totale += valeur
Warning
Le meilleur ratio local ne garantit pas toujours la meilleure combinaison globale.
9. Choix de l'heuristique (sac à dos)⚓︎
Trois critères de tri
- par valeur décroissante — « le plus de valeur d'abord » ;
- par poids croissant — « le plus léger d'abord » ;
- par ratio
valeur/poidsdécroissant — « le plus rentable par kilo ».
Les heuristiques peuvent diverger (capacité 50)
| Objet | Valeur | Poids | Ratio |
|---|---|---|---|
| A | 60 | 10 | 6,0 |
| B | 100 | 20 | 5,0 |
| C | 120 | 30 | 4,0 |
- valeur → C+B = 220 (= optimum) ;
- poids / ratio → A+B = 160 → le ratio rate l'optimum.
Aucune heuristique n'est toujours la meilleure (capacité 10)
Gros (11, 10), Petit1 (6, 5), Petit2 (6, 5) :
- valeur → Gros = 11 ;
- ratio → Petit1+Petit2 = 12 (= optimum) → la valeur rate l'optimum.
Warning
Pour le sac 0/1, aucun glouton n'est garanti optimal.
10. Glouton optimal : sous quelles conditions ?⚓︎
| Problème | Glouton optimal | Glouton non optimal |
|---|---|---|
| Monnaie | système canonique (euro) | système non canonique ({1,3,4}) |
| Sac à dos | sac fractionnaire (sécable) | sac 0/1 (indivisible) |
Montrer qu'un système est non canonique
Exhiber une seule somme où une autre combinaison fait moins de pièces.
Ex : {1,3,4} pour 6 → glouton 4+1+1 (3 pièces) vs 3+3 (2 pièces).
Sac fractionnaire vs sac 0/1
- fractionnaire (on peut prendre une fraction d'objet) → le ratio est optimal ;
- 0/1 (objet entier ou rien — notre cas) → le ratio peut échouer.
11. Coût des gloutons⚓︎
Coût mesuré selon n (types de pièces / objets)
| Algorithme | Meilleur cas | Pire cas |
|---|---|---|
Monnaie (division // et %) |
O(n) | O(n) |
| Sac à dos (tri sélection + parcours) | O(n²) | O(n²) |
| Sac à dos (tri natif + parcours) | O(n log n) | O(n log n) |
Le tri domine
Le parcours du sac est en O(n), mais le tri préalable domine : O(n log n) (tri natif) ou O(n²) (tri sélection) — et non O(n). C'est ce coût qui compte « dans le cas de données nombreuses ».
12. Voyage avec stations-service⚓︎
Étapes
- connaître les distances entre étapes et l'autonomie ;
- cumuler les distances depuis le dernier plein ;
- vérifier si l'étape suivante reste accessible ;
- sinon, s'arrêter à la dernière station accessible ;
- enregistrer son numéro (et la distance) ;
- poursuivre jusqu'à la fin ;
- détecter une étape supérieure à l'autonomie (impossible).
cumul = 0
arrets = []
for i in range(len(distances)):
if cumul + distances[i] > autonomie:
arrets.append(i - 1) # dernière station accessible
cumul = 0
cumul += distances[i]
13. TSP par plus proche voisin⚓︎
Étapes
- choisir une ville de départ ;
- lister les villes non visitées ;
- lire les distances depuis la ville actuelle (distancier) ;
- choisir la plus proche non visitée ;
- l'ajouter au trajet ;
- mettre à jour la distance totale ;
- recommencer ;
- revenir au départ.
def ppv(depart, villes, distancier):
trajet = [depart]
actuelle = depart
non_visitees = [v for v in villes if v != depart]
total = 0
while non_visitees:
proche = non_visitees[0] # pas de lambda
for v in non_visitees:
if distancier[actuelle][v] < distancier[actuelle][proche]:
proche = v
total += distancier[actuelle][proche]
trajet.append(proche)
non_visitees.remove(proche)
actuelle = proche
total += distancier[actuelle][depart] # retour au départ
trajet.append(depart)
return trajet, total
Pourquoi tester plusieurs départs ?
Le résultat dépend de la ville de départ : en essayer plusieurs augmente la chance d'obtenir un bon trajet (le glouton n'est pas garanti optimal).
14. Construire un distancier⚓︎
Étapes
- utiliser les coordonnées ;
- appliquer
√((x₂−x₁)² + (y₂−y₁)²); - mettre 0 sur la diagonale ;
- utiliser la symétrie (
d[i][j] = d[j][i]) ; - vérifier unités et calculs.
import math
d = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
15. Pseudo-code et programmation⚓︎
Identifier dans un algorithme glouton
- les entrées et la sortie ;
- les structures utilisées (listes, dictionnaire, distancier) ;
- l'initialisation ;
- la boucle et le choix glouton ;
- les mises à jour (somme, poids, total…) ;
- la condition d'arrêt.
Documenter et tester
Ajouter une docstring (rôle, paramètres, résultat) et des tests (assert)
sur de petits exemples dont on connaît la solution.
16. Terminaison⚓︎
| Problème | Pourquoi l'algorithme termine |
|---|---|
| Rendu de monnaie | la somme diminue (ou l'indice avance) |
| Sac à dos | le parcours des objets est fini |
| Voyage | l'indice des stations avance |
| TSP | le nombre de villes non visitées diminue |
Correction
- correction partielle : si l'algo s'arrête, le résultat est valide ;
- terminaison : il s'arrête toujours ;
- correction totale : les deux à la fois (mais pas forcément optimal !).
Variant (terminaison) et invariant (correction)
- variant = quantité entière ≥ 0 qui décroît strictement → utile pour une boucle non bornée (
while) ; une boucleforfinie termine d'office ; - invariant = propriété vraie avant la boucle et préservée à chaque tour.
Monnaie (while) : variant = somme (décroît) ; invariant = somme_initiale = somme + pièces déjà choisies.
Sac (for borné) : termine d'office ; invariant = poids_total ≤ capacité → solution réalisable.
17. Tableaux de trace⚓︎
Modèles de tableaux
Monnaie | Pièce | Somme avant | Nombre pris | Somme après | |---|---|---|---|
Sac à dos | Objet | Ratio | Poids courant | Décision | Valeur totale | |---|---|---|---|---|
Voyage | Station | Distance cumulée | Prochaine étape | Arrêt ? | |---|---|---|---|
TSP | Ville actuelle | Villes restantes | Distances | Ville choisie | Total | |---|---|---|---|---|
18. Erreurs fréquentes⚓︎
| Erreur | Cause / correction |
|---|---|
| Pièces dans le mauvais ordre | trier décroissant |
| Valeur / indice confondus | pieces[i] ≠ i |
| Oubli de mettre à jour le reste | somme -= pieces[i] |
| Boucle infinie | la pièce doit faire diminuer la somme |
| Ne pas vérifier que la somme atteint 0 | tester le reste final |
| Croire le glouton toujours optimal | fournir un contre-exemple |
| Dépasser la capacité du sac | tester poids_total + poids <= capacite |
| Trier sur la mauvaise donnée | trier selon le critère demandé |
Calculer poids/valeur |
c'est valeur/poids |
| Oublier le retour à la ville de départ | ajouter distancier[actuelle][depart] |
| Revisiter une ville | la retirer des non visitées |
| Oublier la dernière station accessible | s'arrêter avant de tomber en panne |
| Ne pas détecter une étape impossible | étape > autonomie → pas de solution |
19. Questions-réponses corrigées⚓︎
Vocabulaire⚓︎
1. (N1) Qu'est-ce qu'un algorithme glouton ?
Un algorithme qui fait à chaque étape le meilleur choix immédiat, sans retour en arrière.
2. (N1) Différence entre optimum local et global ?
Le local est le meilleur proche ; le global est le meilleur absolu.
3. (N2) Qu'est-ce qu'une solution réalisable ?
Une solution qui respecte les contraintes (sans être forcément la meilleure).
4. (N2) Qu'est-ce que le ratio dans le sac à dos ?
valeur / poids : l'intérêt d'un objet par unité de poids.
5. (N1) Le glouton garantit-il l'optimum ?
Non.
Compréhension⚓︎
6. (N1) Pourquoi trier les pièces avant le rendu ?
Pour prendre d'abord les plus grandes (choix glouton).
7. (N2) Pourquoi {4,3,1} pour 6 met-il le glouton en défaut ?
Il donne 4+1+1 (3 pièces) au lieu de 3+3 (2 pièces).
8. (N2) Pourquoi tester plusieurs villes de départ au TSP ?
Le trajet dépend du départ ; cela améliore le résultat.
9. (N3) Pourquoi le meilleur ratio ne garantit-il pas le meilleur sac ?
Un bon choix local peut empêcher une meilleure combinaison globale.
10. (N2) Que signifie « le glouton se bloque » (monnaie) ?
Le reste final n'est pas 0 : pas de solution trouvée.
Traces⚓︎
11. (N1) Rendu de 6 avec {4,3,1} : pièces prises ?
4, 1, 1 (3 pièces).
12. (N2) Rendu de 31 avec {10,5,2} glouton : que se passe-t-il ?
10+10+10 puis reste 1 → bloqué.
13. (N2) Sac capacité 5, objets de poids 3 puis 3 : que prend-on ?
Le premier (3) ; le second dépasse (3+3>5).
14. (N3) TSP depuis A : comment choisit-on la 2ᵉ ville ?
La non visitée la plus proche de A dans le distancier.
15. (N3) Voyage : étape de 120 km, autonomie 100 : conclusion ?
Impossible (étape > autonomie).
Méthode⚓︎
16. (N1) Comment vérifier qu'un rendu est complet ?
Le reste final doit valoir 0.
17. (N2) Comment décider si un objet entre dans le sac ?
Si poids_total + poids <= capacite.
18. (N2) Comment calculer un ratio ?
valeur / poids.
19. (N3) Comment trouver un contre-exemple au glouton ?
Sur un petit système, exhiber une solution meilleure que le glouton.
20. (N3) Comment construire un distancier ?
Distance euclidienne entre coordonnées ; 0 sur la diagonale ; matrice symétrique.
Correction d'erreurs⚓︎
21. (N1) Pièces triées croissant : conséquence ?
Le glouton prend les petites d'abord : résultat incorrect.
22. (N2) Oubli de somme -= piece : conséquence ?
Boucle infinie (la somme ne diminue pas).
23. (N2) poids / valeur au lieu de valeur / poids : erreur ?
Le tri est faussé : utiliser valeur / poids.
24. (N3) Oubli du retour au départ (TSP) : conséquence ?
La distance totale est fausse (trajet non bouclé).
25. (N2) Revisiter une ville au TSP : erreur ?
La retirer des villes non visitées après l'avoir choisie.
Programmation⚓︎
26. (N1) Initialiser les compteurs de pièces.
choisies = [0] * len(pieces).
27. (N2) Compléter la condition du while de rendu.
while pieces[i] <= somme:.
28. (N2) Tester si un objet rentre dans le sac.
if poids_total + poids <= capacite:.
29. (N3) Écrire la distance euclidienne entre deux points.
math.sqrt((x2 - x1)**2 + (y2 - y1)**2).
30. (N4) Choisir la ville la plus proche (sans lambda).
proche = non_visitees[0]
for v in non_visitees:
if distancier[actuelle][v] < distancier[actuelle][proche]:
proche = v
Heuristique, coût et preuve⚓︎
31. (N2) Citer trois heuristiques pour le sac à dos.
Par valeur décroissante, par poids croissant, par ratio valeur/poids décroissant.
32. (N3) Le ratio garantit-il l'optimum du sac 0/1 ?
Non (capacité 50 : ratio → 160, optimum → 220). Il est optimal pour le sac fractionnaire.
33. (N2) Quel est le coût du sac à dos glouton ?
O(n log n) : le tri domine le parcours en O(n) (O(n²) avec un tri par sélection).
34. (N2) Quel est le coût du rendu de monnaie (version division) ?
O(n), identique au meilleur et au pire des cas.
35. (N3) À quoi servent un variant et un invariant ?
Le variant prouve la terminaison (quantité ≥ 0 décroissante) ; l'invariant prouve la correction partielle (propriété préservée).
36. (N3) Comment montrer qu'un système est non canonique ?
Donner un contre-exemple : {1,3,4} pour 6 → glouton 3 pièces, optimum 2.
20. Exercices flash corrigés⚓︎
Choisir la pièce suivante : reste 7, pièces {5,2,1}
La pièce 5 (la plus grande ≤ 7).
Compléter un tableau de monnaie : rendre 8 avec {5,2,1}
5 + 2 + 1 → 3 pièces.
Trouver un contre-exemple : système {4,3,1}, somme 6
Glouton 4+1+1 (3) vs optimal 3+3 (2).
Calculer un ratio : valeur 12, poids 4
12 / 4 = 3.
Décider si un objet tient : poids 4, courant 3, capacité 5
Non (3 + 4 = 7 > 5).
Choisir une station : cumul 90, étape 20, autonomie 100
S'arrêter : 90 + 20 = 110 > 100.
Compléter un pseudo-code : mise à jour de la somme
somme = somme - pieces[i].
Justifier la terminaison du sac à dos
Le parcours des objets est fini.
Calculer une distance entre (0,0) et (3,4)
√(9 + 16) = 5.
Choisir la ville la plus proche de A : B=5, C=2, D=8
C (distance 2).
À retenir absolument⚓︎
Principe glouton
- choix local optimal à chaque étape, sans retour en arrière ;
- rapide, mais optimalité non garantie (toujours pouvoir donner un contre-exemple).
Méthode de chaque problème
- Monnaie : pièces triées décroissant, prendre tant que ≤ somme, reste = 0 ;
- Sac à dos : trier (souvent par ratio
valeur/poids), prendre si le poids rentre ; - Stations : cumuler les distances, s'arrêter à la dernière station accessible ;
- TSP : plus proche voisin, revenir au départ, tester plusieurs départs.
Outils & terminaison
- distancier : distance euclidienne, 0 sur la diagonale, symétrique ;
- terminaison : une quantité diminue (somme, objets, stations, villes restantes) ;
- correction totale = correction partielle + terminaison (≠ optimalité).
Prolongements (non étudiés)
Les autres méthodes d'optimisation (programmation dynamique, exploration complète…) ne sont pas au programme de ce chapitre.