Emmanuel Beffara
12 ou 18 avril 2019
On cherche à obtenir une somme \(S\) en utilisant des pièces de \(1\), \(2\), \(5\), \(10\), \(20\) et \(50\), avec un nombre total de pièces minimal.
p := [0, 0, ..., 0]
pour chaque i de 1 à n:
tant que v[i] <= S:
p[i] := p[i] + 1
S := S - v[i]
Les algorithmes dits gloutons servent à résoudre certains problèmes d’optimisation.
On procède de façon séquentielle, en faisant à chaque étape le choix qui semble localement le meilleur.
On ne revient jamais en arrière.
Il s’agit d’une progression descendante, à chaque étape on fait un choix puis on résoud un problème plus petit issu de ce choix.
En général, le fait que le résultat soit correct est facile, le fait qu’il soit optimal n’est pas évident.
On a un ensemble d’activités, chacune caractérisée par une heure de début et une heure de fin, qui veulent utiliser une même ressource.
Comment en planifier le plus grand nombre possible?
Trame générale:
trier A selon un critère approprié
S := { }
pour chaque a dans A:
si a est compatible avec tous les éléments de S:
S := S + { a }
renvoyer S
Quel critère faut-il appliquer?
trier A par valeurs croissantes de f
S := { }
t := 0
pour chaque a dans A:
si d(a) >= t:
S := S + { a }
t := f(a)
renvoyer S
Coût en temps de l’algorithme: \(O(n \log n)\)
Deux activités \(a\) et \(b\) sont compatibles si et seulement si \(f(a) \leq d(b)\) ou \(f(b) \leq d(a)\).
Une solution est un sous-ensemble maximal d’éléments deux-à-deux compatibles.
Dans une solution \(\{a_1,\ldots,a_m\}\) ordonnée par heure de fin croissante, on a donc \[ d(a_1) < f(a_1) \leq d(a_2) < f(a_2) \leq \cdots \leq d(a_m) < f(a_m) \]
Soit \(S=\{a_1,\ldots,a_m\}\) le résultat renvoyé par l’algorithme, avec \(f(a_1) \leq \cdots \leq f(a_m)\). On montre par récurrence que pour tout \(k \leq m\), il existe une solution optimale qui commence par \(a_1,\ldots,a_k\).
Soit une solution optimale \(T\) qui contient \(a_1,\ldots,a_k\), pour un certain \(k<m\). Soit \(b\) l’élément suivant \(a_k\) dans \(T\). Alors:
donc \(T\setminus\{b\}\cup\{a_{k+1}\}\) est une solution.
Elle a même cardinal que \(S\) et elle contient \(a_1,\ldots,a_{k+1}\).
Le cas initial \(k=0\) est immédiat.
Par conséquent \(S\) est une solution optimale.
Trouver un arbre couvrant de poids maximal dans un graphe pondéré.
On se donne un graphe connexe \(G=(S,A)\) et une pondération \(w\).
T := { }
pour chaque a dans A, par valeurs décroissantes de w:
si T + { a } est acyclique:
T := T + { a }
renvoyer T
L’algorithme renvoie forcément un arbre couvrant:
Tous les arbres couvrants on le même nombre d’arêtes
(= nombre de sommets – 1).
Reste à montrer que le poids de l’arbre obtenu est maximal.
Soient \(T\) et \(U\) deux arbres couvrants, soit \(a \in U \setminus T\). Il existe \(b \in T \setminus U\) tel que \(U \setminus \{a\} \cup \{b\}\) est un arbre couvrant.
Démonstration:
Soit \(T\) l’arbre renvoyé par l’algorithme.
Supposons que \(T\) n’est pas de poids maximal.
Donc \(T\) est de poids maximal.