Académique Documents
Professionnel Documents
Culture Documents
ALGORITHMES GLOUTONS
I-Introduction
Les méthodes algorithmiques peuvent être regroupées en familles, parmi lesquelles figurent des algorithmes dits gloutons.
Les algorithmes gloutons permettent de résoudre des problèmes d'optimisation.
Un problème d’optimisation est un problème algorithmique dans lequel l’objectif est de trouver la «meilleure» solution (selon
un critère donné) parmi un ensemble de solutions également valides mais potentiellement moins bonnes.
2- Définition
Un algorithme glouton est un algorithme qui effectue à chaque instant, le meilleur choix possible sur le moment, sans
retour en arrière ni anticipation des étapes suivantes, dans l'objectif d'atteindre au final le résultat optimal.
Les algorithmes gloutons sont parfois appelés algorithmes gourmands ou encore algorithmes voraces.
La solution obtenue par un algorithme glouton n'est pas forcement optimale, mais reste acceptable quand on ne connait
pas d'algorithme exact efficace. Néanmoins, pour certains problèmes, on peut prouver l'optimalité.
Exemple: Il s'agit de trouver un chemin partant de la racine de l'arbre et dont la somme des étiquettes est la plus grande
possible.
Solution de l'algorithme glouton Solution optimale exacte
L'ensemble des 𝑛 activités peut être modélisé par une liste de tuples 𝑺 = [(𝒅𝟎 , 𝒇𝟎 ), (𝒅𝟏 , 𝒇𝟏 ), , . . . , (𝒅𝒏−𝟏 , 𝒇𝒏−𝟏 )] où
𝒅𝒊 représente la date de début de l'activité i et 𝒇𝒊 sa date de fin.
On suppose que pour tout 𝒊 , 𝒅𝒊 < 𝒇𝒊 et que l'activité i se déroule pendant l'intervalle [𝒅𝒊 ; 𝒇𝒊 [
Deux activités i et j sont dites compatibles si 𝒅𝒊 > 𝒇𝒋 ou alors 𝒅𝒋 > 𝒇𝒊
La question peut alors se reformuler comme suit : on cherche un sous-ensemble d'activités compatibles dont le nombre
d'éléments est le plus grand possible.
La technique la plus basique pour résoudre ce type de problème consiste à énumérer de façon exhaustive toutes les solutions
possibles, puis à choisir la meilleure.
Cette approche dite par force brute, toujours possible, est couteuse, en effet dans notre cas on aura 2𝑛 sous-ensembles à
vérifier ce qui donne une complexité exponentielle. On cherche donc une stratégie plus rapide : un algorithme glouton.
Exemple:
S=[ (1,4) , (0,6) , (3,5) , (12,13) , (8,11) , (8,12) , (3,13) , (6,10) , (5,9) , (4,8) , (5,7) , (13,16) , (15,17) , (16,19)]
Algorithme glouton.
1. Trier les activités 𝑺 selon un ordre et un critère
2. Initialiser une liste 𝑸 des activités choisies.
3. Parcourir dans l'ordre la liste 𝑺 des activités, et rajouter l'activité courante à 𝑸 si elle n'est pas incompatible avec celles déjà
présentes dans 𝑸
Sur quel critère faut-il trier la liste des activités?
Stratégie 1 : trier les activités par ordre croissant des durées 𝒇𝒊 − 𝒅𝒊
c d e
Cette approche ne donne pas toujours un résultat optimal.
𝑎 b Dans le cas de figure suivant, l'algorithme choisira les deux activités a
et b, à la place des trois activités c, d et e
Stratégie 2 : trier les activités par ordre croissant de leur date de début 𝒅𝒊
b c d Cette approche ne donne pas toujours un résultat optimal.
Dans le cas de figure suivant, l'algorithme choisira l'activité a à la
𝑎
place des trois activités b, c et d
Stratégie 3 : trier les activités par ordre croissant de leur date de fin 𝒇𝒊 (la bonne idée)
S = [(1,4),(3,5),(0,6),(5,7),(4,8),(5,9),(6,10),(8,11),(8,12),(12,13),(3,13),(13,16),(15,17),(16,19)]
Ecrire la fonction activites_choisies(S) qui prend en entrée la liste des activités S et qui renvoie une liste d'activités à
programmer 𝑸 en utilisant la stratégie 3. Quel est sa complexité.
>>>activites_choisies(S)
[(1, 4), (5, 7), (8, 11), (12, 13), (13, 16), (16, 19)]
On souhaite enregistrer sur une mémoire de taille 𝑀 un groupe de fichiers F=[(𝑛𝑜𝑚0 , 𝑡0 ), … (𝒏𝒐𝒎𝒏−𝟏 , 𝒕𝒏−𝟏 )]. Supposons que
∑𝑡𝑖 > 𝑀 ∶ on ne peut pas enregistrer tous les fichiers. Il s’agit donc de choisir le sous ensemble 𝑄 des fichiers à enregistrer. On
pourrait souhaiter le sous-ensemble qui contient le plus grand nombre de fichiers.
Un algorithme glouton pour ce problème pourrait par exemple ranger les fichiers par ordre croissant des 𝒕𝒊 . Supposons que
les 𝐹𝑖 soient ordonnés par taille (𝒕𝟎 ≤ 𝒕𝟏 , … , ≤ 𝒕𝒏−𝟏 ).
1. Écrivez la fonction fichiers(F,M) utilisant la stratégie présentée ci-dessus qui permet de renvoyer une liste des
booléens 𝑺 de même taille que 𝑭, tel que 𝑆[𝑖] = 𝑇𝑟𝑢𝑒 si 𝐹𝑖 est dans 𝑸 et 𝑆[𝑖] = 𝐹𝑎𝑙𝑠𝑒 sinon. Quelle est sa complexité ?
>>>F=[("A",700),("B",1200),("C",200),("D",50),("E",900)]
>>> fichiers(F,1000)
[True, True, True, False, False]
2. Écrivez la fonction fichiers2(F,M) utilisant la stratégie présentée ci-dessus qui permet de renvoyer la liste Q des
fichiers enregistrés.
Un automobiliste souhaite se rendre en voiture d'une ville A de départ à une autre ville B d'arrivée.
le réservoir de la voiture plein lui permet de rouler R Km
L'automobiliste connait la liste des pompes à essence disponibles sur la route, donnée sous la forme : S=[d0,d1,...,dn-1]
Où chaque di donne la distance qui le sépare de son précédent :
S[0] est à d0 kilomètres du départ
S[1] est à d1 kilomètres de S[0] Etc.
On suppose 𝒅𝒊 ≤ 𝑹 pour 𝒊 = 𝟎. . 𝒏 − 𝟏, dn-1 symbolisant l'arrivée.
L'automobiliste souhaite faire le moins d'arrêts possibles
1. Donnez une condition nécessaire et suffisante pour que l’automobiliste puisse effectuer le parcours. On la supposera
réalisée par la suite.
2. Écrire la fonction stations(S,R) renvoyant la liste des indices des pompes à essence où l'on doit s'arrêter.
Une méthode consiste à toujours aller le plus loin possible sans faire le plein, c’est-à-dire à faire systématiquement le plein
à la dernière station avant la panne sèche...
Pour un réservoir de R=250 Km et la liste S=[120, 142, 90, 70, 130, 150, 84, 25, 110]
>>>S=[120, 142, 90, 70, 130, 150, 84, 25, 110]
>>>R=250
>>>Q=stations(S,R)
>>>print(Q)
[0, 2, 4, 6]
>>>print([S[i] for i in Q])
[120, 90, 130, 84]