Chapitre 16 : Algorithmes gloutons.

Introduction:

L'idée d'un algorithme glouton est simple : à chaque étape, il choisit la solution qui semble la meilleure sur le moment, sans regarder les conséquences futures. Il avance en prenant les décisions les plus optimales localement, en espérant que cela mènera à une solution optimale globale.

Mais cela pose une question : est-ce que ce qui paraît le meilleur choix à court terme est toujours le bon choix à long terme ? Si une décision immédiate semble bonne, peut-elle nous conduire vers un résultat sous-optimal par la suite ?

1. Les Algorithmes Gloutons

Les algorithmes gloutons sont une approche de résolution de problèmes qui consiste à faire des choix localement optimaux à chaque étape, dans l'espoir que ces choix mèneront à une solution globale optimale.

2. Problème du rendu de monnaie :

Le problème du rendu de monnaie est un problème d'algorithmique. Il s'énonce de la façon suivante : étant donné un système de monnaie (pièces et billets), comment rendre une somme donnée de façon optimale, c'est-à-dire avec le nombre minimal de pièces et billets ?

Par exemple, la meilleure façon de rendre 7 euros est de rendre un billet de cinq et une pièce de deux, même si d'autres façons existent (rendre 7 pièces de un euro, par exemple). On rencontre des problèmes similaires dans l'utilisation des boites à poids.

Ce problème est NP-complet dans le cas général, c'est-à-dire difficile à résoudre. Cependant pour certains systèmes de monnaie dits canoniques, l'algorithme glouton est optimal, c'est-à-dire qu'il suffit de rendre systématiquement la pièce ou le billet de valeur maximale — ce tant qu'il reste quelque chose à rendre.

Lien wikipedia

3. Exercice :

A faire dans le cahier.

Imaginons que dans un distributeur, il manque certaines pièces ou billets. Par exemple, il n'y a plus de billets de 5 euros.

Donner un exemple où un algorithme de rendu de monnaie de type gloutons va se tromper et ne pas trouver la solution optimale.

4. Exercice : (sujet 46 - 2025)

On considère dans cet exercice un algorithme glouton pour le rendu de monnaie. Pour rendre une somme en monnaie, on utilise à chaque fois la plus grosse pièce possible et ainsi de suite jusqu’à ce que la somme restante à rendre soit nulle.

Les pièces de monnaie utilisées sont :

pieces = [1, 2, 5, 10, 20, 50, 100, 200]

On souhaite écrire une fonction rendu_monnaie qui prend en paramètres :

  • un entier somme_due représentant la somme à payer ;
  • un entier somme_versee représentant la somme versée qui est supérieure ou égale à somme_due;
  • et qui renvoie un tableau de type list contenant les pièces qui composent le rendu de la monnaie restante, c’est-à-dire de somme_versee - somme_due.

Ainsi, l’instruction rendu_monnaie(452, 500) renvoie le tableau [20, 20, 5, 2, 1].

Compléter ce code et le tester.

Exemples :

>>> rendu_monnaie(700, 700)
[]
>>> rendu_monnaie(102, 500)
[200, 100, 50, 20, 20, 5, 2, 1]
# Pièces disponibles (en centimes d'euro) pieces = [1, 2, 5, 10, 20, 50, 100, 200] def rendu_monnaie(somme_due, somme_versee): '''Renvoie la liste des pièces à rendre pour rendre la monnaie lorsqu'on doit rendre somme_versee - somme_due''' rendu = ... a_rendre = ... i = len(pieces) - 1 while a_rendre > ...: while pieces[i] > a_rendre: i = i - 1 rendu.append(...) a_rendre = ... return rendu print(rendu_monnaie(452, 500))

Tests :

Affichage :

Console:


    
>>>

5. Exercice : Les boites (sujet 33 - 2025)

On dispose d’un ensemble d’objets dont on connaît, pour chacun, la masse. On souhaite ranger l’ensemble de ces objets dans des boites identiques de telle manière que la somme des masses des objets contenus dans une boîte ne dépasse pas la capacité \(c\) de la boîte. On souhaite utiliser le moins de boîtes possibles pour ranger cet ensemble d’objets.

Pour résoudre ce problème, on utilisera un algorithme glouton consistant à placer chacun des objets dans la première boîte où cela est possible.

Par exemple, pour ranger dans des boîtes de capacité \(c = 5\) un ensemble de trois objets dont les masses sont représentées en Python par la liste [1, 5, 2] on procède de la façon suivante :

  • Le premier objet, de masse 1, va dans une première boite.
  • Le deuxième objet, de masse 5, ne peut pas aller dans la même boite que le premier objet car cela dépasserait la capacité de la boite. On place donc cet objet dans une deuxième boîte.
  • Le troisième objet, de masse 2, va dans la première boîte.

On a donc utilisé deux boîtes de capacité \(c = 5\) pour ranger les 3 objets.

Compléter la fonction Python empaqueter(liste_masses, c) suivante pour qu’elle renvoie le nombre de boîtes de capacité c nécessaires pour empaqueter un ensemble d’objets dont les masses sont contenues dans la liste liste_masses. On supposera que toutes les masses sont inférieures ou égales à c.

Exemples :

>>> empaqueter([1, 2, 3, 4, 5], 10)
2
>>> empaqueter([1, 2, 3, 4, 5], 5)
4
>>> empaqueter([7, 6, 3, 4, 8, 5, 9, 2], 11)
5
def empaqueter(liste_masses, c): """Renvoie le nombre minimal de boîtes nécessaires pour empaqueter les objets de la liste liste_masses, sachant que chaque boîte peut contenir au maximum c kilogrammes""" n = len(liste_masses) nb_boites = 0 boites = [0 for _ in range(n)] for masse in ...: i = 0 while i < nb_boites and boites[i] + ... > c: i = i + 1 if i == nb_boites: ... boites[i] = ... return ... liste = [1, 2, 3, 4, 5] contenance = 5 print(f"Il est nécessaire d'utiliser {empaqueter(liste, contenance)} boites.")

Tests :

Affichage :

Console:


    
>>>