Vous êtes sur la page 1sur 13

CORRECTION FICHE TD ALGORITHMIQUE IN_3

Exercice 1

1) Expliquez la différence entre les notations O() et Ω(), sans donner leur définition formelle.

O() exprime une borne supérieure sur la consommation de ressources. Ω() exprime une borne
inférieure sur la consommation de ressources.

2) Les algorithmes diviser-pour-régner et de programmation dynamique sont tous deux basés sur
une relation de récurrence. Expliquez cependant la différence fondamentale entre les deux
techniques de conception.

Diviser-pour-régner procède de haut en bas, alors que la programmation dynamique


procède de bas en haut.

3) Qu’est-ce qu’un algorithme vorace ?

Un algorithme vorace est un algorithme qui fait toujours le choix qui lui semble le
meilleur sur le moment. Autrement dit, il fait le choix localement optimal, dans l’espoir
que ce choix conduira à une solution globalement optimale.

Exercice 2

1) Complexité

Le «if» s’exécute en O(1) et le «return» effectue 3 T(n-1) appels récursifs; la complexité du code
précédent sera donc sous la forme T(n) = 3*T(n-1) + 1 avec T(0) = 1. on aura donc:
T(n) = 3 * T(n-1) + 1
= 3( 3T(n-2) + 1) +1 = 32 T(n-2) + 3 + 1
= 33 T(n-3) + 3² + 3 + 1

= 3n T(0) + 3^(n-1) + 3^(n-2) + … + 3 + 1 or T(0) = 1
= 3n + 3^(n-1) + 3^(n-2) + … + 3 + 1
= [ 3^(n+1) – 1] / 2 ~ 3^n → T(n) = O(3n)

2) Algorithme

int T(int n ) {

int T[] = new int();


if (n ≤ 0 ){
return 1;
else
return T[n-1] * 3; // juste T(n-1) appels récursifs
}

return T[n];
}

Complexité: O(n)
Exercice 3

1) T(n) = 2 T(n/2 + 17) + n


il faut utiliser la substitution pour prouver que T(n) = O(n log n) car T(n) a la même
complexité qu’un T’(n) = 2 T’(n/2) + n dont la complexité ( O(n log n ) )est facile à obtenir car
classique.
Supposons donc que T(n/2) ϵ O(n/2 log n/2) et montrons que T(n) ϵ O(n log n); il existe alors c ϵ R
tq T(n/2 + 17) ≤ c n/2 log n/2 → 2 T(n/2 + 17) ≤ c n log n/2 = c n (log n – log 2)
→ 2 T(n/2 +17) + n ≤ c n (log n – log 2) + n pour c > 1 / log 2 on aura
→ T(n) < c n log n d’où T(n) = O(n log n)

2) On a T(n) = 3 T(n/2) + n
0 n T(n) = 3 T(n/2) + n
/ | \
1 n/2 n/2 n/2 T(n/2) = 3 T(n/ 2²) + n/2
/ | \
2 n/2² … n/2² T(n/2²) = 3 T(n/2³) + n/2²

k 1 … 1 T(n/2^k) = 3 T(2^k+1) +
n/2^k

on a n/2^k = 1 → k = log2 n
c0 = 3⁰ n
c1 = 3(n/2) = 3/2 n
c2 = 3² (n/2²) = (3/2)² n

ck = 3^k (n/2^k) = (3/2)^k n

T(n) = c0 + c1 + … + ck
= n( 1 + 3/2 + (3/2)² + … + (3/2)^k)
= n ( (3/2)^k+1 – 1 ) / 3/2 – 1
= 2n ( (3/2)^log2 n – 1)
or (3/2)^log2 n = elog2 n . ln 3/2
= e ln n / ln 2 (ln 3 – ln 2)
= e ln n (log3 2 – 1 ) ~ e ln n = n
T(n) = 2 n . n → T(n) = O(n²)

3) T(n) = 2 T( n1/2) + log n (on doit effectuer un changement de variable ici)


Pour se faciliter la tâche, on ne se préoccupera pas d’arrondir les valeurs comme √n à l’entier le
plus proche. Si l’on fait le changement de variable m = lg n, on obtient
T(2m) = 2T(2m/2) + m .
Si l’on pose maintenant S(m) = T(2m) , on obtient la nouvelle récurrence
S(m) = 2S(m/2) + m , Effectivement, la nouvelle récurrence a la même solution : S(m) = O(m lg m).
En repassant de S(m) à T(n), on obtient
T(n) = T(2m) = S(m) = O(m lg m) = O(lg n lg lg n).

pour les questions 4 et 5, procédez comme précédemment

6) Méthode générale
T(n) = 2T(n/2) + n lg n ,
bien qu’elle ait la forme correcte : a = 2, b = 2, f (n) = n lg n et nlogb a = n. On pourrait
penser que le cas 3 de la méthode générale s’applique, puisque f (n) = n lg n est plus grande
asymptotiquement que nlogb a = n. Le problème est qu’elle n’est pas polynomialement plus grande.
Le rapport f (n)/nlogb a = (n lg n)/n = lg n est asymptotiquement plus petit que n´ pour
toute constante positive ´. En conséquence, la récurrence tombe dans le fossé situé
entre le cas 2 et le cas 3

Exercice 4:

Soit la suite T (n) définie par T (2) = T (1) = T (0) = 1 et:


T (n) = T (n − 1) + 2 ∗ T (n − 2) + T (n − 3); n > 2
On considère le problème de calculer T (n) pour l’entrée n. Soit l’algorithme naïf récursif associé:
int T(int n){
if (n<=2) return 1;
else return T(n-1)+2*T(n-2)+T(n-3);}
Q 1. Soit A(n) le nombre d’appels récursifs à T effectués lors de l’exécution de la function T (n).
Exprimez
A(n) en fonction de A(n − 1); A(n − 2); A(n − 3). Qu’en déduire sur la complexité de l’algorithme
naïf ?
on suppose qu’on compte dans A(n) l’appel principal. On a donc:
A(n) = 1 si n ≤ 2
A(n) = 1 + A(n − 1) + A(n − 2) + A(n − 3) si n > 2
Donc on peut par exemple en déduire que: A(n) > 3A(n − 3) si n > 2.
Et donc A(n) > 3n÷3.
Q 2. Proposez un algorithme en O(n) (en supposant qu’on est dans le cadre du coût uniforme, i.e. en
ne
prenant pas en compte la taille des opérandes).
int T(int n){
if (n<=2) return 1;
int[] T=new int[n];
T[0]=1;
T[1]=1;
T[2]=1;
for (int i=3; i <=n; i++)
T[i]=T[i-3]+T[i-2]+T[i-1];
return T[i];
}
int T(int n){
if (n<=2) return 1;
int A=1, B=1, C=1, D;
for (int i=3; i <=n; i++){
D=A+2*B+C;
A=B; B=C; C=D;}
return C;
}
Exercice 5

1) Le cas le plus défavorable intervient pour le tri rapide quand la routine de partitionnement
produit un sous-problème à n − 1 éléments et une autre avec 0 élément.
Sa complexité est O(n²)

2) Dans le partitionnement le plus équilibré possible, PARTITION produit deux sousproblèmes de


taille non supérieure à n/2, vu que l’un est de taille n/2 et l’autre de
taille récurrence du temps d’exécution est alors
T(n) 2T(n/2) + Q(n) , D’après le cas 2 du théorème général (théorème 4.1), la solution en est T(n)
= O(n lg n)

3) Supposons, par exemple, que l’algorithme de partitionnement produise systématiquement un


découpage dans une proportion de 9 contre 1, ce qui paraît à première vue assez déséquilibré. On
obtient dans ce cas la récurrence
T(n) T(9n/10) + T(n/10) + cn
pour le temps d’exécution du tri rapide ; nous avons explicitement inclus la constante c
implicitement contenue dans le terme Q(n). La suivante montre l’arbre récursif de cette récurrence.
Remarquez que chaque niveau de l’arbre a un coût cn, jusqu’à ce qu’une condition aux limites soit
atteinte à la profondeur log10/9 n = Q(lg n), après

Arbre récursif de TRI-RAPIDE dans lequel PARTITION produit toujours une décomposition 9-1,
donnant ainsi un temps d’exécution O(nlgn).

Exercice 6

1) Étant donné que


T(n) = 2T(⌊n/4⌋) + 3 log n
trouvons le comportement asymptotique de T(n). Justifiez votre réponse.
On utilisera le Master Theorem avec les coefficients a = 2, b = 4 et la perturbation f(n) = log n. On
trouve d’abord l’exposant :
k = log4 2 = 1/2.
On voit que la perturbation est petite log n = o(nk−ε), en choisissant, par exemple ε = 0, 1.
Effectivement
log n = o(n0.4) puisque le logarithme croit moins vite que n’importe quelle puissance positive.
Par Master Theorem on obtient donc :
T(n) = Θ(n1/2) = Θ(√n).

2) L’algo diviser-pour-régner de cours calcule xn comme suit :


–si n = 0, 1, 2 on renvoie 1, x, x ∗ x respectivement ;
–sinon si n est pair alors on calcule d’abord y = xn/2, et ensuite xn = y ∗ y ;
–sinon (si n est impair) alors on calcule d’abord y = x⌊n/2⌋, et ensuite xn = y ∗ y ∗ x ;
Pour n = 13 ça donne : x13 = y ∗ y ∗ x avec y = x6. A son tour y = z ∗ z avec z = x3. Finalement
z = x ∗ x ∗ x. En tout on a 5 multiplications.
On a trouvé plusieurs solutions différentes de celle-là mais toujours en 5 opérations. Exemple :
y = x² = x ∗ x; z = x³ = y ∗ x; v = x⁵ = y ∗ z; x^13 = v ∗ v ∗ z.

Exercice 7

#include <stdio.h>
#define MAX 100
int main(void){
int i,j,n; int T[MAX][MAX];
printf("Entrez le nombre de lignes d´esir´e (<100)");
scanf("%d",&n);
for(i=0;i<n;i++){
T[i][0]=1;
T[i][i]=1; }
for(i=1;i<n;i++)
for(j=1;j<i;j++)
T[i][j]= T[i-1][j-1]+T[i-1][j];
for(i=0;i<n;i++){
for(j=0;j<i+1;j++)
printf("%3d ",T[i][j]);
printf("\n");}
return 0; }

Sa complexité est de O(n²)

Exercice 8

Avec un tableau trié:


la recherche séquentielle effectue k comparaison pour trouver un élément qui figure dans le
tableau avec k le rang de l’élément dans le tableau. Elle effectue n comparaisons pour trouver un
élément qui n’y figure pas.
Pour trouver un élément dans un tableau trié de taille n avec la recherche dichotomique, on
le cherche d’abords dans le tableau de taille n, puis dans celui de taille n/2, puis dans celui de taille
n/2² ,…, jusque dans celui de taille n/2^k = 1. Sa complexité est de l’ordre de log2 n.

Avec un tableau non trié:


Recherche séquentielle:
pire des cas ( l’élément n’est pas dans le tableau), complexité en O(n)
meilleur des cas (l’élément est en position 1), complexité O(1)
en moyenne c’est en O(n) car on effectuera k comparaisons pour trouver l’élément avec 1<
k<n

recherche dichotomique:
la complexité dans le pire des cas se fera en O( log n ).

Exercice 9

Coupons le tableau en deux moitiés : A[s..m] et A[m + 1..f]. Les trois cas ci-dessous correspondent
à trois positions de l’élément de milieu A[m] par rapport à l’intervalle [a, b]
À gauche : A[m] < a. Dans ce cas-là tous les éléments de la moitié gauche du tableau sont aussi <
a, et
ne peuvent pas appartenir à l’intervalle demandé [a, b]. On va chercher la valeur encadrée dans la
moitié droite seulement.
Dedans :a 6 A[m] 6 b. On a déjà trouvé une valeur encadrée A[m]. On retourne son indice.
À droite :b < A[m]. Ce cas est symétrique au premier, la recherche peut être limitée à la moitié
gauche
du tableau.
Cette analyse mène à la fonction récursive suivante chercher(s,f) qui renvoie l’indice de la valeur
encadrée
dans le tableau A[s..f] (ou ⊥ s’il n’y en a pas. On suppose que le tableau A, et les bornes a,b sont
des
variables globales.
fonction chercher(s,f)
// cas de base
si (s=f)
si (A[s] ∈ [a; b])
retourner s
sinon retourner ⊥
// on divise pour régner
m=(s+f)/2
si A[m] < a
ind= chercher(m+1,f)
sinon si a 6 A[m] 6 b
ind=m
sinon
ind=chercher(s,m)
retourner ind

Analysons sa complexité.
On a réduit un problème de taille n à un seul problème de la taille n/2 et des petits calculs
en O(1), donc la complexité satisfait la récurrence :
T(n) = T(n/2) + O(1).
En la résolvant par Master Theorem on obtient que T(n) = O(log n).

Exercice 10
1) Algorithme 1 Naïf
pour i de 1 à n faire
c←0
pour j de 1 à n faire
si E[j] = E[i] alors
c←c+1
si c > n/2 alors
retourner E[i] est majoritaire
retourner Pas d'élément majoritaire.
Complexité : nombre total de comparaisons = n².

2) Principe :
Couper E en deux tableaux E1 et E2 de tailles n/2 (on suppose n pair).
S'il existe un élément majoritaire x dans E, alors x est majoritaire dans au moins une
des deux listes E1 et E2 (en eet si x non majoritaire dans E1, ni dans E2, alors dans E,
cx ≤ n/4 + n/4 = n/2).
Algorithme récursif : calculer les éléments majoritaires de E1 et de E2 (s'ils existent) avec le
nombre total d'occurences de chacun et en déduire si l'un des deux est majoritaire dansE.
L'algorithme suivant Majoritaire(i, j) renvoie un couple qui vaut (x, cx) si x est majoritaire dans le
sous tableau E[i..j] avec cx occurences et qui vaut (−, 0) s'il n'y a pas de majoritaire dans E[i..j],
l'appel initial étant Majoritaire(1, n). La fonction Occurence(x, i, j) calcule le nombre d'occurences
de x dans le sous-tableau E[i..j].

Algorithme 2 Majoritaire(i, j)
si i = j alors
retourner (E[i], 1)
sinon
(x, cx) = Majoritaire(i, b(i + j)/2c)
(y, cy) = Majoritaire(b(i + j)/2c + 1, j)
si cx 6= 0 alors
cx ← cx + Occurence(x, b(i + j)/2c + 1, j)
si c
y 6= 0 alors
c
y ← cy + Occurence(x, i, b(i + j)/2c)
si cx > b(j − i + 1)/2c alors
retourner (x, cx)
sinon
si c
y > b(j − i + 1)/2c alors
retourner (y, cy)
sinon
retourner (−, 0)

Complexité : le nombre total de comparaisons dans le pire des cas C(n) vérie la relation (on
suppose que n est une puissance de 2) :
C(n) = 2(C(n/2) + n/2) avec C(1) = 0
On en déduit C(n) = n log2(n). : avec le théorème général de résolution des récurrences du Cormen :
Soient a ≥ 1 et b > 1 deux constantes, soit f(n) une fonction et soit T(n) dénie pour les entiers non
négatifs par la récurrence T(n) = aT(n/b) + f(n). T(n) peut alors être borné de la façon suivante.
1. Si f(n) = O(nlogb a−ϵ) pour une certaine constante > 0, alors T(n) = Θ(nlogb a).
2. Si f(n) = Θ(nlogb a), alors T(n) = Θ(nlogba log n).
3. Si f(n) = Ω(nlogb a+ϵ) pour une certaine constante > 0, et si af(n/b) ≤ cf(n) pour une
certaine constante c < 1 et pour tout n susamment grand, alors T(n) = Θ(f(n)).
Ici f(n) = n = Θ(n), on est dans le deuxième cas, et C(n) = Θ(nlog2 2 log n)
3) Pour améliorer l'algorithme précédent, on va se contenter dans un premier temps de mettre au
point un algorithme possédant la propriété suivante : soit l'algorithme garantit que E ne possède pas
d'élément majoritaire, soit l'algorithme fournit un entier p > n/2 et un élément x tels que x
apparaisse au plus p fois dans E et tout élément autre que x apparaît au plus n − p fois dans E.
Remarque :soit x vériant la propriété, alors aucun autre élément z 6= x ne peut être majoritaire (car
cz ≤ n−p < n/2), donc, dans ce cas, x est un candidat-majoritaire. Autrement dit un algorithme
vériant les propriétés de l'exercice nous fournit :
soit la garantie qu'il n'existe aucun élément majoritaire,
soit un candidat-majoritaire x, dont on peut vérier ensuite s'il est vraiment majoritaire en
reparcourant une fois le tableau (soit n − 1 comparaisons).
Remarque :un élément majoritaire x est bien un candidat-majoritaire avec p = cx (donc
s'il existe un majoritaire, il sera bien proposé comme candidat-majoritaire par l'algorithme).

Algorithme 3 Candidat − majoritaire(E)


si E n'a qu'un élément x alors
retourner (x, 1)
sinon
couper E en deux tableaux E1 et E2 de taille n/2
appeler Candidat − majoritaire(E1) qui renvoie AUCUN ou (x, p)
appeler Candidat − majoritaire(E2) qui renvoie AUCUN ou (y, q)
suivant la réponse pour E1 et E2, faire
si AUCUN et AUCUN alors
retourner AUCUN
si AUCUN et (y, q) alors
retourner (y, q + n4 )
si (x, p) et AUCUN alors
retourner (x, p + n4 )
si (x, p) et (y, q) alors
si x 6= y alors
si p > q alors
retourner (x, p + n2 − q)
si p < q alors
retourner (y, q + n2 − p)
si p = q alors
retourner AUCUN // (sinon ce serait x ou y mais cx ≤ n2 et cy ≤ n2 )
sinon // x = y
retourner (x, p + q)

Complexité : on a supposé n une puissance de 2, le nombre de comparaisons C(n) pour un tableau à


n éléments vérifie : C(n) = 2C(n2 ) + 1 avec C(1) = 0, ce qui donne C(n) = n − 1.

Exercice11

1) N(0) = 0, N(1) = 1, N(2) = 2, N(3) = 2, N(4) = 2, N(5) = 1

2) Algorithme Glouton :
| Trier les types de pièces par valeur décroissante.
| Pour chaque valeur de pièces, maximiser le nombre de pièces choisies.
Plus formellement, soit R la somme restante, initialisée `a S. Pour chaque valeur vi,
prendre ci = R / vi pièces, et poser R = R − ci ∗ vi.
Pour prouver l’optimalité de l’algorithme glouton avec les valeurs 5; 2 et 1 :
| Au plus une pièce de 1 (sinon une de 2)
| Au plus deux pièces de 2 (sinon une de 5 et une de 1)
| Le nombre de pièces de 5 est donc bx5c
| Conclure avec ce qui précède

Exercice 12

1)
| Trier les types de pièces par valeur décroissante.
| Pour chaque valeur de pièces, maximiser le nombre de pièces choisies.
Plus formellement, soit R la somme restante, initialisée `a S. Pour chaque valeur vi,
prendre ci = E [R / vi ] pièces, et poser R = R − ci ∗ vi.

Prouvons l’optimalité
l’algorithme retournera:
- au plus une pièce de 5 (sinon une pièce de 10)
- au plus deux pièces de 2 ( sinon une de 5 et une de 1)
- au plus une pièce de 1 (sinon une de 2)
- au plus trois pièces différentes de 10 pour R < 9

2)
- trier les pièces par ordre décroissant de valeur;
- pour chaque valeur de pièce choisie, maximiser son nombre.

3- Soit E = {10, 7, 1} et R = 14, l’algorithme renverra une pièce de 10 et quatre de 1, alors


l’optimalité est atteinte avec deux pièces de 7

4- Avec E’ = {4, 2} et R = 5, l’algorithme renvoie une pièce de 4 mais le problème n’est pas résolu.

Exercice 13

1- Algorithme glouton
- ranger les objets par ordre décroissant d’efficacité (Ei = Vi / Wi)
- pour le premier objet choisi, prendre autant de masse que possible jusqu’à remplissage du sac ou
épuisement de stock;
- faire de même avec le deuxième et ainsi de suite.

2- la complexité dépendra ici du tri choisi

3- Avec la variante « tout ou rien », l’algorithme n’ est plus optimal.


Contre-exemple: on désire remplir un sac de masse 10kg avec des objets A, B et C tels que:
VA = 21, WA = 7 → EA = 3; VB = 6, WB = 3 → EB = 2 et VC = 10 WC = 10 → EC = 1 . Le
programme nous retournera les objets A et B, alors que le choix optimal est fait en choisissant
l’objet C

Exercice 14

1- FONCTION Vorace (C)


S = Ø // À Yaoundé, aucun poste n’a été choisi
TANT que Dschang n’est pas atteint
i = prochain poste rencontré
Si le plein est nécessaire pour se rendre au poste i+1
Ajouter i à S // faire le plein
Retourner S

2- Solution : C1, C3, C7, C10

Exercice 15

1- P(0, j) = 1 ( A a déjà gagné la série et j > 0)


P(i, 0) = 0 ( A a déjà perdu la série et i > 0)

2-
Algorithme récursif :
P(i, j) :
Si i = 0 et j > 0 :
P := 1
Sinon
Si i > 0 et j = 0 :
P := 0
Sinon
Si i > 0 et j > 0 :
P := q1*P(i - 1,j) + q2*P(i, j - 1)
Fsi
Fsi
Fsi

T(k) = temps d’exécution de P(i, j) avec k = i+j


Equation de récurrence : T(k) = 2T(k1) + b
Solution : T(k) = C12k + C2
donc T(k) est en O(2k) ou encore en O(2i+j)
P(n, n) prend un temps dans l’ordre de O(4^n) (car 2^2n = 4^n)

3-

Pour S = 1, i+j
P[0, S] := 1
P[S, 0] := 0
Pour k=1, S1
P[k, Sk] := q1P[k1, Sk] + q2P[k, Sk1]
Finpour
Finpour
Le temps d’exécution est en O(n²) pour le calcul de P(n,n).

Exercice 16

tableau à deux dimensions


algo: somme := 0
pour cptL := 1 à nfaire {pour chaque ligne}
pour cptC := 1 à n faire {pour chaque colonne}
somme := somme + tab[cptL, cptC]

1. complexité spatiale : n * n
2. complexité temporelle : n* n sommes

tableau à une dimension

somme := tab[1].val
pour cpt := 2 à mfaire somme := somme + tab[cpt].val

3. complexité spatiale : 3 * m
4. complexité temporelle : m-1

La complexité temporelle est toujours favorable à la représentation avec un tableau à 1 dimension.


La complexité spatiale l’est également tant que 3 * m < n * n, c’est à dire m < (n*n)/3.

Exercice 17

1- C’est une instance de sac-à-dos fractionnaire (avec le pouvoir calorifique qui remplace le coût
dans
le problème). L’algo glouton de cours est comme ceci :
–Classer les produits dans l’ordre décroissant de coûts par kilo (ici pouvoir calorifique).
–Prendre autant de premier produit que possible (jusqu’au remplissage de sac ou épuisement de
stock).
–Pareil pour le deuxième produit etc. . .
Cela donne les produits classés comme ceci : essence, charbon, ethanol, bois.
Et le contenu de sac : essence - tous les 10 kg ; charbon - tous les 12 kg ; ethanol - 13 kg. Le sac est
plein

2-
a)
L’observation principale est la suivante : si un sommet est noir, alors tous ses voisins doivent être
blancs ; et vice versa. Ainsi on fixe la couleur d’un sommet (par exemple noir) ; on colorie tous ses
voisins en blanc ; tous leurs voisins en noir etc (en fait c’est un parcours en largeur). Soit on arrive à
colorier ainsi tout le graphe, soit on découvre une anomalie, et dans ce cas-là le 2-coloriage est
impossible.
Voici le pseudo-code (en supposant que le graphe est représenté par les listes d’adjacence, est
Adj(v) est la liste des voisins du sommet v). Tous les sommets sont gris au départ, et on les colorie
en parcourant le graphe.

W est la file d’attente.


pour tout v
v.couleur=gris
s= un sommet quelconque
W= file vide de sommets
s.couleur=noir
W.enfiler(s)
tant que W non vide
v= W.défiler
maCouleur=v.couleur
autreCouleur=inverser(maCouleur)
pour tout u dans Adj(v)
si u.couleur =maCouleur
Imprimer("coloriage impossible !")
exit
si u.couleur = gris
u.couleur=autreCouleur
W.enfiler(u)
Imprimer("coloriage trouvé !")

b) La complexité est la même que pour le parcours en profondeur O(|V| + |E|)

c)
Si l’algorithme dit "coloriage trouvé", alors tous les sommets sont coloriés (il ne reste plus de
sommets gris), parce que le BFS (parcours en profondeur) dans un graphe connexe non-orienté
visite tous les sommets. Les voisins de chaque sommet blanc sont noirs et vice versa grâce à la
boucle principale (s’il y avait deux voisins de même couleur, ça serait détecté au moment ou le
deuxième voisin sort de la file). On a donc démontré que si l’algo dit "coloriage trouvé", alors c’est
vraiment le cas.
Pour la réciproque, il reste à prouver, que si le coloriage est possible l’algorithme le trouvera.
Effectivement, si le coloriage est possible, alors il existe un coloriage où le sommet s est noir (sinon
on inverse la couleur de tous les sommets). Dans ce coloriage tous les voisins de s doivent être
blanc, tous leurs voisins noirs etc (c-à-d tous les sommets à une distance paire de s sont noirs, tandis
que les sommets à une distance impaire sont blanc). Mais c’est exactement le coloriage calculé par
l’algorithme !

d)
Malheureusement cette méthode ne marche pas pour 3 couleurs (ou plus) puisque la couleur d’un
sommet
ne détermine pas les couleurs de ses voisins comme c’était le cas pour 2 couleurs.

Exercice 18

1. On ne se soucie d’abord pas de la hauteur des livres. Pour minimiser le nombre


d’étagères, l’algorithme glouton suivant semble tr`es naturel :
S Algo range livres :
i←1;
etagere ← 1 ;
largeur libre ← L ;
tant que i ≤ n faire
si wi ≤ largeur libre
largeur libre ← largeur libre − wi
sinon
etagere ← etagere + 1
largeur libre ← L − wi
fin si
placer le livre bi sur l’étagere etagere
fin tant que
Montrons que cet algorithme est optimal : supposons qu’il existe une solution Opt qui utilise moins
d’étagères que la solution S proposée par cet algorithme. Alors, il existe un premier livre bi placé
par Opt sur une étagère k strictement inférieure `a l’étagère k′ choisie par la solution S (on choisit i
minimum). Soit bj le premier livre placé sur l’étagère k dans la solution S (j < i). Par minimalité
de i, Opt place bj sur la même étagère k. Opt place donc tous les livres de bj `a bi (et peut-être
d’autres encore) sur une seule étagère. Donc Pi l=j wl < L. Par conséquent, l’algorithme glouton
pouvait aussi placer le livre bi sur l’étagère k, une contradiction. Donc S est optimale.

2-
On peut maintenant régler la hauteur des étagères. Nous allons donc chercher `a minimiser
l’encombrement, défini comme la somme des hauteurs du plus grand livre de chaque étagère
utilisée. On voit dans l’exemple suivant que l’algorithme glouton précédent ne trouve pas la
solution optimale.
On pose L = 3, n = 3, w1 = 2, w2 = w3 = 1, h1 = 1, h2 = h3 = 7. L’algorithme glouton place b1 et b2
sur la première étagère, de hauteur 7, et b3 sur une deuxième étagère, de hauteur 7 aussi, fournissant
un encombrement total de 14. La solution optimale fournit un encombrement total de 8 en plaçant
b1 seul sur la première étagère et b2 et b3 sur la deuxième étagère.

Fait par EM

Vous aimerez peut-être aussi