A
Lector Dr. Paul Iacob
Asistent Drd. Lucian Sasu
Universitatea Transilvania din Brasov
Facultatea de Matematic a si Informatic a
Catedra de Informatic a
Octombrie 2003
2
Cuprins
1 Introducere 7
1.1 Scopul cursului . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Generalit at i . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 Limbajul pseudocod 11
2.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Limbajul pseudocod . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3 Analiza algoritmilor 17
3.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Analiza algoritmilor . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Algoritmi parametrizat i (subalgoritmi) . . . . . . . . . . . . . 21
3.4 Notat ia asimptotic a . . . . . . . . . . . . . . . . . . . . . . . . 24
3.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4 Structuri elementare de date 27
4.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2 Structuri liniare . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.3 Stiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.1 Alocarea secvent ial a a stivei . . . . . . . . . . . . . . . 29
4.3.2 Alocarea nl ant uit a a stivei . . . . . . . . . . . . . . . . 29
4.4 Coada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.4.1 Alocarea secvent ial a a cozii . . . . . . . . . . . . . . . 31
4.4.2 Alocarea nl ant uit a a cozii . . . . . . . . . . . . . . . . 32
4.5 Arbori binari . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.5.1 Alocarea secvent ial a a unui arbore binar . . . . . . . . 34
4.5.2 Alocarea nl ant uit a a unui arbore binar . . . . . . . . . 34
4.5.3 Alocarea mixt a a unui arbore binar . . . . . . . . . . . 35
4.6 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3
4.7 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5 Recursivitate 39
5.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.3.1 Calcularea lui n! . . . . . . . . . . . . . . . . . . . . . 45
5.3.2 Sirul lui Fibonacci . . . . . . . . . . . . . . . . . . . . 45
5.4 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.5 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6 Metoda Backtracking 49
6.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 Exemplu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.4 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.5 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7 Generarea submult imilor 55
7.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.2 Schema general a de lucru . . . . . . . . . . . . . . . . . . . . . 55
7.3 Generarea elementelor unui produs cartezian . . . . . . . . . . 57
7.4 Generarea tuturor submult imilor unei mult imi . . . . . . . . . 58
7.5 Generarea mult imii combin arilor . . . . . . . . . . . . . . . . . 59
7.6 Generarea mult imii permut arilor . . . . . . . . . . . . . . . . . 62
7.7 Generarea mult imii aranjamentelor . . . . . . . . . . . . . . . 65
7.8 Submult imi de sum a dat a . . . . . . . . . . . . . . . . . . . . 67
7.9 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.10 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8 Metoda Divide et Impera 71
8.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 71
8.3 Problema turnurilor din Hanoi . . . . . . . . . . . . . . . . . . 72
8.3.1 Metoda I . . . . . . . . . . . . . . . . . . . . . . . . . . 74
8.3.2 Metoda a IIa . . . . . . . . . . . . . . . . . . . . . . . 75
8.3.3 Metoda a IIIa . . . . . . . . . . . . . . . . . . . . . . 76
8.4 Algoritmul de sortare QuickSort . . . . . . . . . . . . . . . . . 77
8.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
8.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4
9 Sortare si statistici de ordine 83
9.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
9.2 Exemplic ari, generalit at i . . . . . . . . . . . . . . . . . . . . 83
9.3 Determinarea simultan a a minimului si a maximului . . . . . . 84
9.4 G asirea celor mai mici dou a elemente dintrun sir . . . . . . . 85
9.5 Problema select iei . . . . . . . . . . . . . . . . . . . . . . . . . 87
9.5.1 Select ie n timp mediu liniar . . . . . . . . . . . . . . . 87
9.5.2 Select ia n timp liniar n cazul cel mai defavorabil . . . 88
9.6 Heapsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
9.7 Algoritmi de sortare n timp liniar . . . . . . . . . . . . . . . . 92
9.7.1 Algoritmul sort arii prin num arare (CountSort) . . . . . 92
9.7.2 Sortare pe baza cifrelor . . . . . . . . . . . . . . . . . . 94
9.7.3 Sortare pe grupe . . . . . . . . . . . . . . . . . . . . . 95
9.8 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
9.9 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
10 Metoda Greedy 99
10.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 99
10.3 Submult imi de sum a maxim a . . . . . . . . . . . . . . . . . . 100
10.4 Arborele Human . . . . . . . . . . . . . . . . . . . . . . . . . 102
10.5 Interclasare optimal a . . . . . . . . . . . . . . . . . . . . . . . 106
10.6 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
10.7 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
11 Programare dinamic a 111
11.1 Obiective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
11.2 Prezentare general a . . . . . . . . . . . . . . . . . . . . . . . . 111
11.3
Inmult irea unui sir de matrici . . . . . . . . . . . . . . . . . . 112
11.4 Cel mai lung subsir cresc ator . . . . . . . . . . . . . . . . . . . 117
11.5 Rezumat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
11.6 Exercit ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
12 Teste de autoevaluare 121
A Metode utile n calculul complexitat ii 127
A.1 Sume des nt alnite . . . . . . . . . . . . . . . . . . . . . . . . 127
A.2 Delimitarea sumelor . . . . . . . . . . . . . . . . . . . . . . . 128
A.2.1 Induct ia matematic a . . . . . . . . . . . . . . . . . . . 128
A.2.2 Aproximarea prin integrale . . . . . . . . . . . . . . . . 129
A.3 Analiza algoritmilor recursivi . . . . . . . . . . . . . . . . . . 130
5
A.3.1 Metoda iterat iei . . . . . . . . . . . . . . . . . . . . . . 130
A.3.2 Recurent e liniare omogene . . . . . . . . . . . . . . . . 131
A.3.3 Recurent e liniare neomogene . . . . . . . . . . . . . . . 132
B Rezolvari 135
B.1 Rezolv ari pentru capitolul 3 . . . . . . . . . . . . . . . . . . . 135
B.2 Rezolv ari pentru capitolul 4 . . . . . . . . . . . . . . . . . . . 145
B.3 Rezolv ari pentru capitolul 5 . . . . . . . . . . . . . . . . . . . 150
B.4 Rezolv ari pentru capitolul 6 . . . . . . . . . . . . . . . . . . . 153
B.5 Rezolv ari pentru capitolul 7 . . . . . . . . . . . . . . . . . . . 160
B.6 Rezolv ari pentru capitolul 8 . . . . . . . . . . . . . . . . . . . 162
B.7 Rezolv ari pentru capitolul 9 . . . . . . . . . . . . . . . . . . . 165
B.8 Rezolv ari pentru capitolul 10 . . . . . . . . . . . . . . . . . . 168
B.9 Rezolv ari pentru capitolul 11 . . . . . . . . . . . . . . . . . . 174
6
Capitolul 1
Introducere
1.1 Scopul cursului
Lucrarea de fat a si propune s a e un nurs introductiv n teoria algorit-
milor. Se vor introduce not iunile de algoritm, subalgoritm, complexitatea
algoritmilor, diferite metode de programare, probleme clasice. Cursul este
detinat student ilor din anul nt ai, at at de la zi c at si de la forme alternative
(nv at am ant la distanc u a, cursuri postuniversitare).
1.2 Generalitat i
Pentru rezolvarea unei probleme pe calculator, se parcurg urm atorii pasi:
1. se detecteaz a problema;
2. se adaug a restrict iile impuse de domeniul care a creat problema;
3. se creeaz a un model matematic;
4. se concepe un algoritm (un mod) de rezolvare a problemei;
5. se scrie un program;
6. se interpreatez a rezultatele de la calculator n termeni specici dome-
niului problemei.
Pasii 1, 2, 3 sunt n general reunit i sub numele de analiz a. Pasii 4, 5
constituie programarea. Pasul 6 face parte din implementare.
Deci algoritmul reprezint a un pas intermediar ntre modelul matematic
si programul realizat ntr-un program conceput pentru calculator. Originea
7
cuv antului algoritm este legat a de numele Abu Jafar Mohammed Ibn M us a
al Khow arizm, autor arab al unei c art i de matematic a. Not iunea de algoritm
este fundamental a, deci nu se poate deni; n general, ea este explicat a ca o
succesiune nit a de pasi computat ionali care transform a date de intrare n
date de iesire.
Propriet at ile pe care trebuie s a le aibe un algoritm sunt:
1. Fiecare pas trebuie s a cont in a o operat ie bine denit a (de exemplu
urm atoarele operat ii nu sunt bine denite: 4/0 sau scade 10 sau 20
din 30);
2. Pasul care urmeaz a ec arui pas trebuie s a e unic denit;
3. Fiecare pas trebuie s a e efectuabil, adic a s a poat a executat cu cre-
ionul pe h artie: operat ii cu numere ntregi - da, dar operat ii cu numere
reale n general - nu.
4. Trebuie s a se termine n timp nit. Se poate spune c a timpul trebuie
s a e rezonabil de scurt si totusi vor considerat i algoritmi care pe
masinile actuale necesit a zeci de ani pentru c a se presupune c a viitoarele
masini vor mult mai rapide.
Ce vom studia n leg atur a cu algoritmii?
1. Cum s a concepem un algoritm? Crearea unui algoritm nu va nicio-
dat a pe deplin automatizat a, va r am ane o problem a a omului n primul
r and si abia apoi a masinii.
In aceast a ordine de idei vom studia n
acest curs metode de elaborare a algoritmilor.
2. Exprimarea noastr a va restr ans a, din necesitatea de a scrie usor pro-
grame corecte, la algoritmi structurat i, adic a algoritmi care folosesc
anumite structuri specice care vor expuse la nceputul cursului.
3. Vom nv at a s a veric am corectitudinea algoritmilor conceput i. Un al-
goritm corect trebuie s a rezolve problema propus a pentru orice date
de intrare. Nu se pune problema veric arii cu anumite date (acest lu-
cru t ine de vericarea programului), ci problema unei demonstrat ii a
corectitudinii programului (n general ca o teorem a).
4. Nu ajunge s a construim algoritmi corect i! Trebuie s a cunoastem si
performant ele algoritmilor creat i. Pot exista mai mult i algoritmi care
s a rezolve aceeasi problem a, unii mai greu sau mai usor de nteles (de
urm arit), unii mai lungi n num arul de pasi descrisi, dar cu performant a
urm arit a prin analiz a (num arul de pasi elementari executat i, n leg atur a
8
cu dimensiunea intr arii). O alt a problem a este cea legat a de dimensiu-
nea memoriei necesare execut iei programului realizat dup a un anumit
algoritm.
9
10
Capitolul 2
Limbajul psedocod si structuri
fundamentale
2.1 Obiective
1
, a
2
, . . . , a
n
), obt inut prin permu-
tarea valorilor init iale, astfel nc at a
1
a
2
a
n
. Ideile algoritmului
descris mai jos (sortare prin interclasare) pot nt elese dac a ne g andim la
aranjarea c art ilor de joc: avem pe mas a, cu fat a n jos, o serie de c art i pe
care le putem lua una c ate una n m an a, deplas andu-le p an a la locul pe care
trebuie s a l ocupe.
Exemplu: Fie sirul A = 3 1 5 2 7 4 .Acest sir va parcurs de un
cursor i (se ia c ate o carte) si mutat n cadrul sirului cu ajutorul unui cursor
j care parcurge pe A
p an a la locul potrivit:
pentru i = 1:
A
= 3
pentru i = 2, elementul A(2) = 1 este mai mic dec at 3, deci trebuie
pus n fat a lui:
A
= 1 3
pentru i = 3:
A
= 1 3 5
pentru i = 4:
A
= 1 2 3 5
pentru i = 5:
A
= 1 2 3 5 7
pentru i = 6:
A
= 1 2 3 4 5 7
S a observ am c a nu avem nevoie de un spat iu suplimentar pentru rezultat si
putem face ceea ce se numeste sortare in place (pe loc) (i.e. n afara sirului
nu se t in dec at cel mult un num ar constant de elemente ale sirului).
i=2
t
i
6 A(j + 1) = A(j) c
6
n
i=2
(t
i
1)
7 j = j 1 c
7
n
i=2
(t
i
1)
sf arsit c at timp
8 A(j + 1) = k c
8
n 1
sf arsit pentru
9 scrie ( A(i), i = 1, n ) c
9
n
Stop
19
T(n) = c
1
(n + 1) +c
2
(n 1) +c
3
(n 1) +c
4
(n 1) +
+ c
5
i=2
t
i
+ (c
6
+c
7
)
n
i=2
(t
i
1) + (c
6
+c
7
)
n
i=2
(t
i
1) +
+ c
8
(n 1) +c
9
n
Cum putem s a-l a am pe t
i
? O se ne punem, de fapt, problema intervalu-
lui n care se plimb a, studiind cele dou a cazuri care corespund limitelor
intervalului.
Cel mai rapid caz se obt ine c and sirul este gata sortat si deci n linia 5 vom
avea A(j) k pentru orice j = 2, . . . , n deci n acest caz t
i
= 1, iar
T(n) = a n +b, unde a, b constante, deci T funct ie liniar a de n.
Cel mai r au caz se obt ine c and sirul dat este sortat descresc ator, ceea ce
nseamn a c a pe linia 5 vom avea A(j) > k pentru orice j de la i 1 la 1, deci
t
i
= i 1 ; atunci
n
i=2
(i 1) =
n(n1)
2
si
n
i=2
(i 2) =
(n2)(n1)
2
, deci
T(n) = a n
2
+b n +c, funct ie p atratic a de n.
Analiza se face, n general, pentru cel mai r au caz .
S a vedem acum dac a sortarea se poate face altfel, eventual mai repede.
Pentru aceasta vom adopta o alt a metod a, divide et impera. Aceast a
metod a porneste de la ideea c a problema pus a pentru o intrare mare (num ar
mare de date) este mai greu de rezolvat dec at o problem a cu un num ar redus
de date, de exemplu un sir format dintr-un singur element. Principiul divide
et impera funct ioneaz a astfel:
- se mparte problema n mai multe subprobleme
- se rezolv a ecare din subprobleme (n general recursiv)
- se combin a solut iile pat iale ntr-o solut ie nal a
Vom reveni cu am anunte despre aceast a metod a n capitolul 8.
Algoritmul sort arii prin interclasare (mergesort) se bazeaz a pe metoda
divide et impera. S a vedem ce nseamn a interclasarea: din dou a siruri
sortate cresc ator s a se creeze sirul sortat tot cresc ator care cont ine toate
elementele celor dou a siruri init iale.
Aceasta d a urm atorul algoritm:
Start Interclasare
20
citeste( n, (A(i), i = 1, n) )
citeste( m, (B(j), j = 1, m) )
k = 0
i = 1
j = 1
repet a
k = k + 1
dac a A(i) < B(j) atunci
C(k) = A(i)
i = i + 1
altfel
C(k) = B(j)
j = j + 1
sf arsit dac a
p an a c and i > n sau j > m
Ciclul de mai jos poate s a nu se execute nici o dat a
pentru il = i, n
k = k + 1
C(k) = A(il)
sf arsit pentru
Ciclul de mai jos poate s a nu se execute nici o dat a
pentru jl = j, m
k = k + 1
C(k) = B(jl)
sf arsit pentru
Din cele dou a cicluri pentru anterioare, se execut a exact unul singur
scrie( C(kl), kl = 1, m+n )
Stop
Se observ a c a timpul total de execut ie pentru algoritmul de interclasare
este T(n, m) = c (n + m) unde c este timpul maxim necesar execut iei
instruct iunilor din interiorul ciclurilor repet a si pentru (c nu depinde de m, n).
Pentru algoritmul de sortare prin interclasare prezent am not iunea de su-
balgoritm.
3.3 Algoritmi parametrizat i (subalgoritmi)
Rareori un algoritm, ca aceia prezentat i p an a acum, constituie probleme
independente; n general, algoritmii pentru rezolvarea unor probleme com-
plexe au p art i care se combin a ntre ele.
Pentru punerea n evident a a unei astfel de structuri modulare vom folosi
21
algoritmi parametrizat i numit i si subalgoritmi.
Parametrii vor variabile ale c aror valori vin din algoritmul care cheam a
si se ntorc napoi n acesta, deci efectele produse asupra parametrilor de
intrare vor exista si dup a ce subalgoritmul se termin a
1
.
Algoritmul Interclas parametrizat ar : Interclas(A, n, B, m, C) ceea ce
nseamn a: interclaseaz a A (av and n componente) cu B (av and m compo-
nente) si obt ine C.
, n
, B
, m
, C
).
Corespondent a dintre parametrii de chemare si cei din subalgoritm se face
pozit ional.
Pentru usurarea exprim arii, vom considera si subalgoritmi de tip funct ie
care returneaz a o valoare.
In acest caz, valoarea care se determin a de c atre
subalgoritm este atribuit a numelui funct iei.
Exemplu:
ArieCerc(r)
ArieCerc = r r
Return
Apelul unui astfel de subalgoritm se face la fel ca mai nainte.
In plus, va-
loarea returnat a poate folosit a ntro expresie sauntro atribuire:
STotal = ArieCerc(10) 5
partea ntreag a
q este indicele elementului de la jum atatea sirului
cheam a Mergesort(A, p, q)
cheam a Mergesort(A, q + 1, r)
cheam a Merge(A, p, q, r)
sf arsit dac a
Return
Acest algoritm poate folosit de exemplu astfel:
Start Sortare
citeste( n, (A(i), i = 1, n) )
cheam a Mergesort(A, 1, n)
scrie( Sirul sortat este: , (A(i), i = 1, n) )
Stop
Observat ii:
1. Sortarea const a de fapt din interclasarea perechilor de siruri de un
element, de dou a elemente, . . . , p an a c and interclas am o pereche de
siruri de
n
2
elemente, obt in and sirul sortat.
2. Dac a la un moment dat un sir are un num ar impar de elemente, atunci
se va mp art i n dou a subsiruri de dimeniuni care difer a printr-o unitate
(subsirurile sunt c at mai echilibrate ca num ar de elemente).
Vericat i execut ia algoritmului pentru sirul 3 2 5 6 4 1 0 7
23
3.4 Notat ia asimptotica
Pentru a vedea cum se comport a timpul de execut ie al unui algoritm
pentru intr ari mari vom deni funct iile , , O.
Spunem c a T(n) = (f(n)) dac a N, c
1
, c
2
> 0 astfel nc at:
0 < c
1
f(n) < T(n) < c
2
f(n), n > N (3.1)
Spunem c a T(n) = (f(n)) dac a N, c
1
> 0 astfel nc at:
0 < c
1
f(n) < T(n), n > N (3.2)
Spunem c a T(n) = O(f(n)) dac a N, c
1
> 0 astfel nc at:
T(n) < c
1
f(n), n > N (3.3)
L as am n seama cititorului s a demonstreze propriet at ile de mai jos.
Fie F , , O. Atunci:
1. Tranzitivitate:
T(n) = F(f(n)) si f(n) = F(g(n)) T(n) = F(g(n))
2. Reexivitate:
T(n) = F(T(n))
3. Simetrie:
f(n) = (g(n)) g(n) = (f(n))
4. Bisimetrie:
f(n) = O(g(n)) g(n) = (f(n))
f(n) = (g(n)) g(n) = O(f(n))
5. Dac a
M astfel nc at g(n) > f(n), n > M
atunci
(f(n) +g(n)) = (g(n))
6. T(n) = (f(n)) T(n) = O(f(n)) si T(n) = (f(n))
7. (cf(n)) = (f(n)), c constant a > 0
Aplic and propriet at ile 1-7 se demonstreaz a imediat urm atoarele:
24
1. T(n) = a n
2
+b n +c T(n) = (n
2
)
2. T(n) = c
1
n log n +c
2
n +c
3
T(n) = (n log n)
Din cele de mai sus, precum si analiza f acut a la algoritmul de sortare prin
insert ie rezulta c a complexitatea acestuia este T(n) = (n
2
).
Calculul complexit at ii algoritmului de sortare prin interclasare se efectu-
eaz a mai jos.
C and un algoritm cont ine o apelare a lui nsusi se numeste recursiv.
In
acest caz timpul de execut ie se descrie printr-o ecuat ie recursiv a. Pentru
rezolvarea unei asemenea ecuat ii vom folosi metode matematice care vor
descrise n capitolul dedicat metodei Divide et impera.
Ne vom limita acum la a scrie recurent a pentru sortare prin interclasare.
Dac a timpul pentru un sir cu n elemente este T(n), atunci timpul pentru
sirul cu
n
2
elemente va T
_
n
2
_
, deci:
T(n) =
_
a , dac a n = 1
2 T
_
n
2
_
+c n , dac a n > 1
i=1
A(i) B(i). S a se scrie algoritmul pentru calculul
produsului scalar.
3. Se d a n, vectorul A(i), i = 1, n si un num ar x. S a se scrie un algoritm
care g aseste indicele j pentru care A(j) = x (problema c aut arii).
4. Cum se modic a algoritmul de mai sus dac a stim c a vectorul este sortat
cresc ator?
5. Se dau n si vectorul A(i), i = 1, n. S a se g aseasc a cel mai mic element.
6. Reluat i problema anterioar a n situat ia n care trebuie s a aat i c ate
elemente minime sunt.
ARSIT
Din cele n componente ale vectorului, doar componentele x(F), . . . , x(S)
fac parte din coad a.
Algoritmul de intrare n coad a este:
a Coada
dac a S = n atunci
Dep asire
altfel
S = S + 1
x(S) = a
sf arsit dac a
Return
Algoritmul de iesire din coad a este:
a Coada
dac a F > S atunci
Coada este vid a
altfel
a = x(F)
F = F + 1
sf arsit dac a
Return
Se poate imagina usor c a proced and n acest mod (scot and din fat a si in-
troduc and la sf arsit), coada migreaz a spre dreapta si poate s a ajung a n
situat ia de dep asire c and de fapt mai exist a mult loc gol (n vectorul x) pe
primele pozit ii. Apare astfel ideea de a folosi elementele vectorului ca si cum
ar dispuse circular, precum n gura 4.1, pagina 32.
L as am n seama cititorului s a scrie algoritmii de intrare/iesire din coada
circular a.
31
X(1)
X(2)
X(n)
X(F)
X(S) Sfarsit
Fata
Figura 4.1: Coada circular a
4.4.2 Alocarea nlant uita a cozii
Alocareanl ant uit a se face similar cu alocareanl ant uit a a stivei n noduri
de tipul:
INFO LEG
x(F) . . . x(S) *
FAT
A SF
ARSIT
Algoritmul de intrare n coad a este:
a Coada
y LIBERE
INFO(y) = a
LEG(y) =
dac a FAT
A=* atunci
Coada este vid a
FATA=y
altfel
LEG(SF
ARSIT)=y
sf arsit dac a
SF
ARSIT=y
Return
Init ial, coada este vid a, i.e. FAT
A=SF
ARSIT=*.
Algoritmul de iesire din coad a este:
32
a Coada
dac a FATA=* atunci
Coada este vid a
altfel
a = INFO(FATA)
aux =FATA
FATALEG(FATA)
aux LIBERE
sf arsit dac a
Return
4.5 Arbori binari
Un arbore n care orice v arf (nod) are 0, 1 sau 2 descendent i se numeste
arbore binar. Un arbore binar care are v arfuri cu 0 sau 2 descendent i se
numeste arbore binar strict. Un astfel de arbore se poate folosi, de exemplu,
la reprezentarea n memorie a unei expresii aritmetice.
Exemplu: expresia
(a +b) c
2
c
3
se va reprezenta astfel:
Figura 4.2: Arborele binar atasat expresiei aritmetice (a+b) c
2
c
3
. Semnul
este reprezentare pentru operatorul de ridicare la putere.
Frunzele acestui arbore (nodurile f ar a descendent i) cont in operanzii, iar
celelalte noduri cont in operatorii. Deoarece nu toate operat iile sunt comu-
tative, este foarte important dac a un nod este descendent pe st anga sau pe
dreapta. R ad acina unui arbore este nodul care nu este descendentul nim anui.
33
Alocarea unui arbore binar se poate face:
- secvent ial
- nl ant uit
- mixt
4.5.1 Alocarea secvent iala a unui arbore binar
Inainte de apelul Recursiv(2) din algoritmul Exemplu se scrie pe stiv a
adresa de memorie a instruct iunii care se va executa dup a ce se va
reveni din acest apel (n cazul nostru instruct iunea de scriere cu adresa
10):
adr = 10
n = 2
Se apeleaz a Recursiv(2); se scrie pe stiv a valoara parametrului n = 2,
se rezerv a spat iu de memorie pentru i (pentru care nu se atribuie o
valoare anume la nceput):
40
i
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 4, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia nu este ndeplinit a, se
intr a pe ramura altfel.
Avem din nou apel: nainte de acesta se salveaz a adresa de memorie
a instruct iunii de la care se va continua execut ia (incrementarea de la
adresa 100):
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se intr a n Recursiv(1); se salveaz a pe stiv a valoarea parametrului n =
1, se rezerv a spat iu de memorie pentru i (pentru care nu se atribuie o
valoare anume la nceput):
i
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 2, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
41
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia nu este ndeplinit a, se
intr a pe ramura altfel.
Avem din nou apel: nainte de acesta se salveaz a adresa de memorie
a instruct iunii de la care se va continua execut ia (incrementarea de la
adresa 100):
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se intr a n apelul Recursiv(0); se salveaz a pe stiv a n = 0, se rezerv a
spat iu de memorie pentru i (pentru care nu se atribuie o valoare anume
la nceput):
i
n = 0
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se calculeaz a i = 2 n = 0, valoare care se depune n locul rezervat
pentru i la acest apel (n cazul nostru, n v arful stivei):
42
i = 0
n = 0
adr = 100
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Se face testarea n = 0; deoarece este condit ia ndeplinit a, se intr a pe
ramura atunci, care reprezint a ntoarcere la metoda Recursiv(1).
La ntoarcerea din Recursiv(0) n Recursiv(1), se scoate de pe stiv a
informat ia care a fost depus a datorit a apelului Recursiv(0), revenindu
se la forma de dinainte de efectuarea acestui apel:
i = 2
n = 1
adr = 100
i = 4
n = 2
adr = 10
n = 2
Instruct iunea de la care se va continua execut ia este de la adresa 100,
care a fost scoas a de pe stiv a.
Suntem n Recursiv(1). Execut ia se continu a de la instruct iunea cu
adresa 100 (conform punctului precedent), deci i ia valoarea 2 +1 (va-
loareal 2 din sum a ind datorat a informat iei i = 2 de pe stiv a), care se
aseaz a.
Datorit a instruct iunii de retur nale din subalgoritmul Recursiv, avem o
ntoarcere de la Recursiv(1) la Recursiv(2). Se cur at a stiva de informat iile
i = 2, n = 1, adr = 100 si se continu a execut ia de la instruct iunea cu
adresa 100:
i = 4
n = 2
adr = 10
n = 2
43
Suntem n Recursiv(2). Execut ia se continu a de la instruct iunea cu
adresa 100, deci i ia valoarea 4 +1 (valoarea 4 din sum a ind datorat a
informat iei i = 4 de pe stiv a), care se aseaz a.
Datorit a instruct iunii de retur nale din subalgoritmul Recursiv, avem o
ntoarcere de la Recursiv(2) la Exemplu. Se cur at a stiva de informat iile
i = 4, n = 2, adr = 10 si se continuarea execut iei se va face de la
instruct iunea cu adresa 10. Stiva va :
n = 2
Se execut a instruct iunea cu adresa 10: Scrie(Sfarsit).
Se termin a programul (algoritmul Exemplu), iar stiva devine vid a.
In
cazul unei implement ari, controlul ar preluat de c atre sistemul de
operare.
Algoritmul a asat valorile 3, 5. Evident, acest lucru se putea face mult mai
simplu printro iterat ie; dar exemplul de fat a a dorit s a ilustreze funct ionarea
unui apel recursiv. Datorit a operat iilor de cur at are a stivei (care se efectueaz a
printro simpl a incrementare sau decrementare a valorii dintrun registru al
microprocesorului), precum si datorit a informat iilor repetate care se salveaz a
pe stiv a (n, i, adr), timpul si spat iul de memorie necesar sunt mai mari dec at
pentru variantele iterative. Totusi, n destul de multe cazuri implement arile
recursive sunt mult mai usor de urm arit si de nt eles dec at cele recursive.
O observat ie important a: programatorul este singurul r aspunz ator de
faptul c a programul lui se termin a. Altfel spus, trebuie mare atent ie la
impunerea unei condit ii de terminare a recursivit at ii (n cazul nostru, testarea
pentru n = 0).
In caz contrar, un astfel de algoritm implementat va epuiza
spat iul disponibil pentru stiv a si se va opri f ar a a rezolva problema (apel
recursiv la innit).
Dac a revenim la convent ia ca transferul parametrilor s a se fac a prin
adres a, atunci pe stiv a, n cadul ec arui subalgoritm apelat, n loc de va-
loarea lui n sar depus adresa de memorie rezervat a n cadrul algoritmului
(la noi: adresa bazei stivei).
In acest fel, orice modicare care sar face asu-
pra parametrului n din subalgoritmul Recursiv s-ar face de fapt (via aceast a
adres a pus a pe stiv a) asupra valorii lui n din algoritmul Exemplu. Majo-
ritatea limbajelor (Pascal, C/C++, C#, PL/SQL) au mecanisme prin care
se poate stabili dac a pe stiv a se depune o valoare (copia valorii parametru-
lui efectiv) sau o adres a de memorie (adresa la care este stocat parametrul
efectiv).
44
5.3 Exemple
5.3.1 Calcularea lui n!
Pentru un n natural, denim valoarea n! n mod recursiv astfel:
n! =
_
1, pentru n = 0
n (n 1)!, pentru n > 0
(5.1)
Algoritmul recursiv este urm atoarea:
Start FactRec
citeste( n )
scrie( Fact(n) )
Stop
unde subalgoritmul Fact are forma:
Fact(n)
dac a n = 0 atunci
Fact = 1
altfel
Fact = n Fact(n 1)
sf arsit dac a
Return
Complexitatea algoritmului este dat a de ecuat ia recursivu a T(n) = T(n
1) + c, c ind o constant a datorat a apelului recursiv (operat iei cu stiva) si
nmult irii, pentru care solut ia este T(n) = (n) (pentru rezolvarea recurent ei
anterioare, a se vedea A). Varianta iterativ a este de aceeasi complexitate
teoretic a, dar mai rapid a n practic a.
5.3.2 Sirul lui Fibonacci
Sirul lui Fibonacci se deneste astfel:
f(n) =
_
_
_
0, n = 0
1, n = 1
f(n 1) +f(n 2), n 2
(5.2)
Vom implementa recursiv acest algoritm:
Start FiboRec
citeste( n )
scrie( Fibo(n) )
Stop
unde algoritmul recursiv Fibo este:
45
Fibo(n)
dac a n = 0 sau n = 1 atunci
Fibo = n
altfel
Fibo = Fibo(n 1) +Fibo(n 2)
sf arsit dac a
Return
Complexitatea teoretic a este dat a de ecuat ia recursiv a T(n) = T(n 1) +
T(n 2) + c, care duce la T(n) = (
n
), unde =
1+
5
2
(t aietura de
aur)(a se vedea Anexa A) . Complexitatea exponent ial a mare este datorat a
faptului c a se calculeaz a de mai multe ori aceleasi valori: de exemplu, n
f(n) = f(n 1) + f(n 2), f(n 2) este apelat at at pentru calculul lui
f(n 1), c at si pentru cel de al doilea membru al p art ii drepte a ecuat iei
anterioare. Redundant a de calcul devine tot mai accentuat a pentru valori
mici ale argumentului.
S a vedem o implementare iterativ a:
Start FiboIter
citeste( n )
f(0) = 0
f(1) = 1
pentru i = 2, n
f(i) = f(i 1) +f(i 2)
sf arsit pentru
scrie( f(n) )
Stop
Complexitatea algoritmului anterior este evident (n). Acest fapt se dato-
reaz a memor arii valorilor lui f si evit arii calculului repetat (ca n algoritmul
precedent).
5.4 Rezumat
Rezolvarea recursiv a a problemelor este deseori mai usoar a dec at cea ite-
rativ a.
In esent a, orice apel de subalgoritm (recursiv sau nu) determin a
depunerea unor informat ii pe o stiv a gestionat a automat. Codul rezultat
este mai scurt si mai usor de depanat; ns a o implementare recursiv a poate
duce la o complexitate crescut a, datorit a rezolv arii n mod repetat a ace-
lorasi probleme, deci este necesar a de ecare dat a o analiz a pertinent a a
complexit at ii (un exemplu relevant este dat n cele dou a implement ari pen-
tru calculul sirului lui Fibonacci de mai sus).
46
5.5 Exercit ii (rezolvarile la pagina 39)
1. S a se calculeze recursiv maximul unui sir.
2. S a se calculeze recursiv suma elementelor dintrun sir.
3. S a se calculeze puterea a na a unui num ar real a, cu o complexitate
mai bun a dec at (n).
4. S a se dea un contraexemplu pentru care algoritmul de la 3 nu d a
num arul optim de nmult iri.
5. S a se scrie un algoritm care calculeaz a termenul fibo(n) al sirului Fi-
bonacci n timp mai bun de (n) (a se veda si problema 3).
6. S a se dea algoritmi recursivi pentru parcurgerea n preordine, postor-
dine, inordine a unui arbore binar.
47
48
Capitolul 6
Metoda Backtracking
6.1 Obiective
Acest capitol introduce una din cele mai generale modalit at i de rezolvare
a problemelor: metoda Backtracking. Ea duce la scrierea unor algoritmi care
evit a generarea tuturor combinat iilor posibile si apoi la validarea rezultatelor.
Este prezentat a schema general a de algoritm backtracking si probleme clasice
pentru a c aror rezolvare se foloseste aceast a abordare.
6.2 Prezentare generala
Metoda Backtracking se poate aplica algoritmilor care trebuie s a constru-
iasc a o solut ie de forma
x = (x(1), x(2), . . . , x(n)) (6.1)
unde pentru orice i 1, 2, . . . , n, x(i) A
i
, A
i
ind o mult ime dat a ca
informat ie de intrare si unde, n plus, componentele lui x trebuie s a mai
satisfac a niste condit ii interne.
Exemplu: s a consider am:
A
1
= A, B, E
A
2
= A, C
A
3
= U, S, E, C
Cerint e:
1. S a se construiasc a cuvintele care au prima liter a din A
1
, a doua liter a
din A
2
, a treia liter a din A
3
;% si care respect a condit iile interne de la
2;
49
2.
In plus, se cere respectarea urm atoarelor condit ii interne:
(a) Nu sunt dou a litere consecutive egale;
(b) Nu sunt formate numai din consoane sau numai din vocale.
Dac a lu am n considerare numai cerint a de la 1, obt inem solut iile admisi-
bile ale problemei, de exemplu (AAU), (ACS), (EAU), (BAU), (BCC), . . . .
Dar (AAU), (BCC) nu respect a condit iile interne 2a, iar (EAU) nu respect a
condit ia 2b.
O metod a de rezolvare a acestei probleme ar s a construim mai nt ai
toate solut iile admisibile si apoi s a veric am care dintre ele respect a condit iile
interne. Acest mod de a aborda problema duce, n exemplul nostru, la 324 =
24 de solut ii din care evident cele carencep cu AA, de exemplu, nu sunt bune.
Dac a mult imile A
1
, A
2
, . . . , A
n
au respectiv k
1
, k
2
, . . . , k
n
elemente, atunci
am avea n total k
1
k
2
. . . k
n
solut ii admisibile. Pentru k
1
= k
2
= = k
n
=
m avem m
n
solut ii admisibile, deci un algoritm de tip brute force care ia n
considerare toate posibilit at ile ar avea o complexitate exponent ial a.
Algoritmul de tip backtracking urm areste micsorarea num arului de ope-
rat ii, dar trebuie s a spunem c a r am ane de complexitate exponent ial a. Acest
algoritm urm areste s a genereze c ate o component a x(k) A
k
c at timp mai
are o component a netestat a din A
k
; dac a nu mai are componente netestate,
se revine la alegerea elementului de pe pozit ia anterioar a x(k 1), altfel se
merge la componenta x(k + 1). In felul acesta s-ar genera toat a mult imea
solut iilor admisibile; dar dac a dup a ce am g asit o component a x(k) test am
dac a bucata de vector (x(1), x(2), . . . , x(k)) generat a p an a atunci satisface
condit iile de continuare derivate din condit iile interne, atunci vom putea s a
nu permitem generarea inutil a a unor solut ii care oricum nu ar bune (n
exemplul nostru (AA )).
Trebuie s a mai subliniem c a simplul fapt c a bucata (x(1), x(2), . . . x(k))
din vectorul x satisface condit iile de continuare nu nseamn a c a o s a g asim,
obligatoriu, o solut ie a problemei (exist a, totusi, o metod a care g aseste solut ia
pas cu pas, f ar a revenire, numit a Greedy; ea va prezentat a mai t arziu).
Schema algoritmului general va :
Backtracking(A, n)
k = 1
c at timp k > 0
dac a k = n + 1 atunci
scrie( (x(i)), i = 1, n )s-a generat o solut ie
k = k 1
altfel
dac a mai exist a valori netestate a A
k
atunci
50
x(k) = a
dac a (x(1), x(2), . . . , x(k)) satisface condit iile de continuare atunci
k = k + 1
sf arsit dac a
altfel
k = k 1
sf arsit dac a
sf arsit dac a
sf arsit c at timp
Return
6.3 Exemplu
Vom utiliza acest algoritm prin problema asez arii damelor pe tabla de
sah astfel nc at oricare dou a dame s a nu se atace (2 dame se atac a dac a sunt
pe aceesi linie, coloan a, diagonal a).
Vom considera mult imile (A
i
)
i=1,n
ca ind pozit iile (de la 1 la n) pe care
le poate ocupa o dam a pe linia i. Evident c a de data aceasta toate mult imile
A
i
sunt egale.
Deci o congurat ie pe o tabl a de n = 5 precum mai jos va simbolizat a
de vectorul solut ie x = (1, 3, 5, 2, 4) si se poate vedea c a n acest caz condit iile
interne sunt respectate (oricare dou a dame nu se bat).
Algoritmul pentru n > 4 este:
Dame(n)
pentru i = 1, n
x(i) = 0init ial pe nici o linie nu avem pozit ionat a nici o regin a
sf arsit pentru
k = 1
c at timp k > 0
dac a k = n + 1 atunci
scrie( (x(i)), i = 1, n )
k = k 1
altfel
x(k) = x(k) + 1
51
dac a x(k) n atunci
dac a DispunereCorecta(x, k)=adevarat atunci
k = k + 1
sf arsit dac a
altfel
x(k) = 0 Nu avem nici o regin a pe aceast a linie
k = k 1 Ne ntoarcem la regina de pe pozit ia anterioar a
sf arsit dac ax(k) n
sf arsit dac a k = n + 1
sf arsit c at timp
Return
DipunereCorecta(x, k) testeaz a dac a condit iile de continuare pentru bucata
x(1), . . . , x(k) sunt ndeplinite; returnaz a adev arat dac a nu avem regine care
se atac a, fals n caz contrar.
DispunereCorecta(x, k)
corect = adevarat presupunem init ial c a nu avem nici un atacntre regina
k si cele dispuse anterior
pentru i = 1, k 1
dac a x(k) = x(i) sau [x(k) x(i)[ = k i atunci
sunt pe aceeasi coloan a sau pe aceeasi diagonal a
corect = fals
sf arsit dac a
sf arsit pentru
DispunereCorecta = corect
Return
6.4 Rezumat
Multe probleme cer generarea uneia/mai multora/tuturor solut iilor care
respect a anumit a cerint e. O abordare de tipul genereaz a toate combinat iile,
apoi ret inele pe cele valide (bruteforce) este posibil a, dar si cea mai ine-
cient a. Metoda backtracking urm areste depistarea c at mai devreme cu
putint a a solut iilor care sunt invalide (pe m asur a ce componentele lor se ge-
nereaz a). Desi algoritmii rezultatt i sunt de complexitate exponent ial a, multe
solut ii admisibile, dar invalide sunt evitate.
52
6.5 Exercit ii (Rezolvarile la pagina 153)
1. Scriet i un algoritm pentru parcurgerea tablei de sah cu un cal (calul
sare pe diagonal a unui dreptunghi cu laturile de un p atrat si dou a
patrate). Fiecare p atrat al tablei trebui s a e vizitat exact o singur a
dat a.
2. Av and 4 culori si o hart a cu n t ari (dat a print-o matrice de adiacent a:
a
ij
= 1 dac a t ara i este vecin a cu t ara j, 0 altfel), s a se coloreze
harta astfel ca dou a t ari vecine s a nu aibe aceeasi culoare (dou a t ari se
consider a a vecine dac a au o frontier a comun a).
3. O organizat ie are n component a sa n b arbat i si m femei. S a se scrie
un algoritm care listeaz a toate modalit at ile n care se poate alc atui o
delegat ie care s a cont in a cel put in k femei, k < m.
4. Cum poate pl atit a o sum a de x lei, n bancnote de valoare v(i),
i = 1, n din care avem c ate b(i) buc at i? S a se dea toate solut iile posibile.
53
54
Capitolul 7
Generarea submult imilor
7.1 Obiective
De multe ori solut iile care se cer pentru rezolvarea unei (sub)probleme
sunt de o form a particular a: produse carteziene, familia submult imilor, a
combinat iilor, aranjamentelor, permut arilor, submult imilor de sum a dat a.
Acest capitol cont ine rezolv ari clasice pentru aceste probleme, n mai multe
variante.
7.2 Schema generala de lucru
O aplicat ie imediat a a metodei Backtracking este generarea submult imilor.
Vom considera sumbult imi ale mult imii A = a(1), a(2), . . . , a(n) cu n ele-
mente. Evident c a avem biject ie ntre mult imea indicilor 1, 2, . . . , n si
elementele mult imii A. Exemplu:
1, 3, 4, 5 a(1), a(3), a(4), a(5)
Ca atare, vom presupune pentru simplicarea algoritmilor c a a(i) = i, i
1, . . . , n.
Avem la dispozit ie urm atoarele modalit at i de reprezentare a unei submult imi
X cu i elemente ale lui A:
1. Printrun vector x cu i componente care cont ine elementele submult imii,
preciz anduse valoarea lui i sau complet and componentele lui x cu o
valoare neutilizat a (de exemplu 0);
2. Analog cu metoda 1, dar plas and elemetele submult imii la sf arsitul
vectorului x;
55
3. Prin vectorul caracteristic al submult imii: un vector c cu n componente
unde c(i) = 1 arat a c a a(i) apart ine submult imii, iar c(i) = 0 arat a c a
a(i) nu apart ine submult imii.
Exemplu: pentru A = 1, 2, 3, 4, 5, 6, 7, submult imea X = 1, 3, 4, 5 poate
reprezentat a astfel:
1. x = (1, 3, 4, 5, 0, 0, 0): elementele din submult imea X la nceput, restul
p an a la n pozit ii ind completate cu o valoare care nu se g aseste n A,
de exemplu 0 (care nu este indice valid);
2. x = (0, 0, 0, 1, 3, 4, 5): elementele din submult imea X la sf arsit, primele
pozit ii ind completate cu o valoare care nu se g aseste n A;
3. c = (1, 0, 1, 1, 1, 0, 0): c este vectorul caracteristic:
c(i) =
_
1, dac a i X
0, dac a i , X
Toate gener arile prezentaten continuare au un caracter iterativ ecare
nou element (i.e. submult ime) al mult imii ind g asit pe baza elementului
anterior.
Algoritmul general pe care l vom prezenta n continuare foloseste, pe
l ang a un vector de dimensiune n (n care apar succesiv elementele submult imii)
si un indicator de generare. Acest indicator de generare are init ial valoarea
0; apoi are valoarea 1 c at timp se mai poate genera o submult ime X si din
nou valoarea 0 c and s-a terminat generarea.
Generare(x, n, ig)
dac a ig = 0 atunci
x = valoarea (submult imea) init ial a
ig = 1
Returniese n (sub)algoritmul apelant
sf arsit dac a
dac a exist a un succesor al lui x atunci
x =succesorul lui xig r am ane 1
altfel
ig = 0nu s-a mai putut genera submult imea X
sf arsit dac a
Return
Un mod de utilizare a acestui algoritm pentru gener ari este urm atorul:
ig = 0
56
repet a
cheam a Generare(x, n, ig)
dac a ig = 0 atunci
exitIesi din ciclare
altfel
cheam a Prelucrare(x, n)prelucreaz a elementul proasp at obt inut al
submult imii
sf arsit dac a
p an a c and fals
i=1
n(i) elemente.
n
ordine lexicograc a este cel n care x
(i + 1) = x(i) + 2, . . . , x
(n) = x(i) +n i + 1.
Se ncepe cu x = (0, 0, . . . , 0) care reprezint a mult imea vid a, iar atunci
c and x = (1, 2, . . . , n) nseamn a c a am generat ultimul element.
Algoritmul pentru generarea submult imilor unei mult imi este:
Submultimi(x, m, ig)
dac a ig = 0 atunci
pentru i = 1, n
58
x(i) = 0
sf arsit pentru
ig = 1
Return
sf arsit dac a
pentru i = n, 1, 1
dac a x(i) < i atunci
x(i) = x(i) + 1
pentru j = i + 1, n
x(j) = x(j 1) + 1
sf arsit pentru
Return
sf arsit dac ax(i) < i
sf arsit pentru
ig = 0
Return
7.5 Generarea mult imii combinarilor
Fie A = 1, 2, . . . n si m n. Vom construi n continuare algoritmi de
generare a tuturor celor C
m
n
combin ari din mult imea A cu proprietatea c a
oricare dou a elemente difer a ntre ele prin natura lor, nu si prin ordine.
O prim a metod a se bazeaz a pe metoda de reprezentare 1. Si de aceast a
dat a vectorii vor generat i n ordine lexicograc ancep and cu x = (1, 2, . . . , m)
2
.
Fiind dat x = (x(1), x(2), . . . , x(m)), urm atorul element x
va determinat
astfel:
1. se determin a indicele i cu proprietatea: x(i) < n m + i, x(i + 1) =
n m+i + 1, . . . , x(m) = n
2. se trece la x
prin:
- x
(i) = x(i) + 1
- x
; pentru
aceasta vom pune n evident a ultima secvent a de cifre 1:
X =(. . . , 0, 1, . . . 1, 0, . . . , 0)
a b
unde a este indicele unde ncepe aceast a secvent a iar b indicele ultimului
element egal cu 1.
Trecerea la x
(a 1) = 1, x
(a) = 0 si n rest x
(i) = x(i) va
determina congurat ia urm atoare.
Dac a a < b atunci rezult a c a x(a 1) = 0. S a not am cu l
1
lungimea
secvent ei de elemente 1, deci l
1
= b a + 1 si cu l
0
lungimea secvent ei de
zerouri de la sf arsitul lui x, deci l
0
= n b. Rezult a c a l
1
2 si l
0
0.
Trecerea de la x la x
se construieste astfel:
Dac a n apare pe o pozit ie m > 1, atunci se face interschimbarea p(m)
p(m 1) si s-a obt inut noua permutare. Dac a p(1) = n, atunci se per-
mut a circular spre st anga cele n elemente, obt in anduse tat al permut arii p.
iB
a(i) = M (7.2)
67
Vom folosi pentru reprezentarea mult imilor B metoda 3, deci dac a x este
vectorul caracteristic al lui B atunci (7.2) se rescrie ca:
n
i=1
x(i) a(i) = M (7.3)
Componentele lui x vor generate succesiv dup a metoda general a bac-
ktracking: dac a am stabilit deja n x componentele x(1), x(2), . . . , x(k 1),
k1
i=1
x(i) a(i) M, atunci componenta x(k) trebuie s a satisfac a condit iile:
k
i=1
x(i) a(i) M (7.4)
si
k
i=1
x(i) a(i) +
n
i=k+1
a(i) M (7.5)
Vom considera
S =
k
i=1
x(i) a(i) (7.6)
si
R =
n
i=k+1
a(i) (7.7)
Vom presupune c a elementele mult imii A sunt sortate cresc ator (se face
o sortare n prealabil). Algoritmul va :
SumbultimiSuma(a, x, n, M, k, S, R, ig)
dac a ig = 0 atunci
pentru i = 0, n
x(i) = 1
k = 1
S = 0
R =
n
i=1
a(i)
sf arsit pentru
altfel
S = S x(k) a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
68
c at timp k > 0
dac a x(k) < 1 atunci
x(k) = x(k) + 1
S = S +x(k) a(k)
dac a S = M atunci
ig = 1
Return
sf arsit dac a
dac a S < M si S +R M atunci
R = R x(k)
k = k + 1
sf arsit dac a
dac a S +R < M atunci
S = S +x(k) a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
altfel
S = S a(k)
R = R +a(k)
x(k) = 1
k = k 1
sf arsit dac a
sf arsit c at timp
ig = 0
Varianta recursiv a, mult mai usor de urm arit este dat a mai jos. Variabila
ramas este egala cu M S din algoritmul precedent.
SubmultimiRecursiv(a, x, n, k, ramas)
dac a ramas = 0 atunci
cheam a Prelucrare(a, x, k 1)
Return
sf arsit dac a
dac a k > n sau ramas < 0 atunci
Return
sf arsit dac a
pentru x[k] = 0, 1
cheam a SubmultimiRecursiv(a, x, n, k + 1, ramas x[k] a[k])
sf arsit pentru
Return
69
7.9 Rezumat
Pentru determinarea unor submult imi (de o natur a particular a) a unei
mult imi exist a algoritmi specializat i. Se pot da, evident, mai mult i algoritmi
pentru generarea unei solut ii. Aceste tipuri de probleme se nt alnesc adeseori
sub o form a mascat a n enunt ul altor probleme, sau ca etap a intermediar a
ntrun caz mai mare.
7.10 Exercit ii (rezolvarile la pagina 160)
1. S a se scrie algoritmi recursivi pentru generarea tipurilor de submult imi
din acest capitol.
70
Capitolul 8
Metoda Divide et Impera
8.1 Obiective
Capitolul prezint a metoda Divide et Impera, ce se poate utiliza atunci
c and rezolvarea unei probleme se face prin spargerea ei n cazuri de dimen-
siune mai mic a (dar de aceeasi natur a cu problema init ial a), iar apoi prin
recombinarea solut iilor obt inute. Determinarea complexit at ii se reduce la
rezolvarea unei recurent e, pentru care o unealt a util a este Teorema central a.
Este dat cel mai ecient algoritm de sortare (Quicksort) si se demonstreaz a
o limit a inferioar a pentru algoritmiide sortate bazat i pe comparat ii.
8.2 Prezentare generala
Aceast a metod a nu este ceva nou pentru cursul nostru. Am rezolvat cu ea
problema sort arii prin interclasare n capitolul 3, pagina 20. Metoda const a
n urm atoarele etape:
1. Partit ionarea problemei init iale n mai multe probleme mai mici;
2. Rezolvarea (de obicei recursiv a) a ec arei subprobleme; dac a o subpro-
blem a este de dimensiune sucient de mic a, atunci ea se poate rezolva
printro metod a ad-hoc, care poate mai put in performant a pentru
cazuri de dimensiune mare;
3. Combinarea rezultatelor part iale pentru a obt ine rezultatul problemei
init iale.
Dac a o problem a a fost divizat a n a subprobleme care au dimensiunea
n
b
si sunt rezolvate recursiv, atunci complexitatea este dat a de formula:
T(n) = aT
_
n
b
_
+f(n) (8.1)
71
unde f(n) este costul combin arii solut iilor subproblemelor.
Aarea formei lui T(n) este o problem a de algebr a care se poate aborda
prin induct ie sau folosind rezultatele teoremei principale din [2]:
Teorema 1. (Teorema central a.) Fie a 1 si b > 1 constante, e f(n) o
funct ie si T(n) denit a pe ntregii nenegativi prin recurent a:
T(n) = aT
_
n
b
_
+f(n) (8.2)
unde interpret am pe
n
b
e ca pe
_
n
b
_
, e ca pe
_
n
b
_
. Atunci T(n) poate
delimitat a asimptotic dup a cum urmeaz a:
1. Dac a f(n) = O(n
log
b
a
) pentru o anumit a constant a > 0, atunci
T(n) = (n
log
b
a
)
2. Dac a f(n) = (n
log
b
a
) atunci T(n) = (n
log
b
a
log n)
3. Dac a f(n) = (n
log
b
a+
) pentru o anumit a constant a > 0 si dac a
af
_
n
b
_
cf(n) pentru o anumit a constant a c < 1 si tot i n sucient i
de mari, atunci T(n) = (f(n)).
Demonstrat ia se poate g asi n [2].
Am folosit divide et impera la sortarea unui sir (sortarea prin interclasare,
algoritmul Mergesort); se vede c a se ajunge la complexitatea:
T(n) = (nlog
2
n)
(care se deduce din cazul 2 al Teoremei centrale), complexitate mai bun a
dec at cea de la sortarea prin insert ie, care era
T(n) = (n
2
)
8.3 Problema turnurilor din Hanoi
Prima problem a pe care o prezent am este Problema turnurilor din Ha-
noi, problem a care nu are nici o leg atur a cu Hanoi-ul, ci este un joc logic
inventat n secolul trecut de matematicianul francez Eduard Lucas. El a
fost cel care a v andut pentru prima oar a aceast a problem a drept joc, cu opt
discuri si trei baghete.
Dup a o str aveche legend a hindus a, zeul Brahma ar xat pe masa tem-
plului s au din Benares trei bastonase verticale de diamant si ar nsirat pe
acesta 64 de discuri de m arimi descresc atoare (de la baz a la v arf), form and
72
astfel un trunchi de con. A dispus apoi ca discurile s a e mutate pe un al
doilea, folosind si al treilea bastonas; zi si noapte trebuia mutat c ate unul
din discurile aate n v arful unuia din bastonase n v arful altui bastonas, res-
pect and n ecare moment ordinea descresc atoare a m arimii discurilor aate
pe ecare bastonas. Legenda spune c a, d and aceast a porunc a, Brahma a
sust inut c a atunci c and se va termina asezarea celor 64 de dicuri pe cel de-al
doilea bastonas, atunci se va sf arsi si viat a pe P am ant. O versiune destul
de optimist a deoarece presupun and c a mutarea unui disc ar dura o secund a,
cele 64 de discuri vor ajunge pe al doilea bastonas n circa 584.942.416.729
de ani.
Enunt ul formalizat al problemei este: e trei tije si n discuri perforate
de diametre diferite. Discurile sunt asezate init ial pe tija 1 n ordinea des-
cresc atoare a diametrelor acestora consider and sensul de la baz a la v arf. Pro-
blema const a n a muta turnul de n discuri de pe tija 1 pe tija 2 ntr-un
num ar minim de mut ari, t in and cont de urm atoarele reguli:
1. La ecare mutare se mut a un singur disc
2.
In permanet a, pe ecare tij a, deasupra unui disc pot mutate numai
discuri de diametre mai mici.
Calcularea num arului minim de pasi: observ am c a pentru 2, 3, 4 si 5 discuri,
problema se rezolv a efectu and un num ar de mut ari egal cu 3, 7, 15 si respectiv
31, de unde putem formula ipoteza c a pentru problema cu n discuri vom
efectua 2
n
1 mut ari.
S a demonstr am valabilitatea acestui rezultat prin induct ie matematic a
complet a dup a n. Am ar atat c a armat ia este adev arat a pentru n = 2, 3, 4, 5
discuri. Presupunem c a ea este adev arat a pentru n discuri, deci sunt necesare
2
n
1 mut ari. Vom demonstra c a pentru n+1 discuri sunt necesare 2
n+1
1
mut ari.
Putem rezolva problema mut arii celor n + 1 discuri n trei etape:
1. Mut am primele n discuri pe tija a treia
2. Mut am al n + 1-lea disc pe a doua tij a
3. Mut am cele n discuri de pe a treia tij a pe cea de-a dou a tij a.
Folosind acest procedeu, sunt necesare:
1. 2
n
1 mut ari pentru realizarea primei etape
2. o mutare pentru realizarea celei de a doua etape
73
3. 2
n
1 mut ari pentru realizarea celei de a treia etape
k=3
T
P
(k) + (n 2)c =
= T
Q
(1) +T
Q
(1) +
n
k=2
T
P
(k) + (n 2)c =
=
n
k=2
T
P
(k) +cn =
n
k=2
c k +c n = (n
2
)
unde am considerat n mod convenabil c a T
Q
(1) este m arginit de acceasi
constant a c care apare n expresia lui T
P
(n).
2n
_
n
e
_
n
2
obt inem c a:
h log
2
n! > nlog
2
n nlog
2
e = (nlog
2
n)
Se obt ine c a T(n) = (nlog
2
n). Am demonstrat deci c a pentru algorit-
mii care se bazeaz a doar pe comparat ii complexitatea nu poate s a scad a
sub nlog
2
n. Pentru cazuri speciale ale sirului ce trebuie sorart, a se vedea
capitolul 9.
8.5 Rezumat
Metoda Divide et Impera se foloseste atunci c and rezolvarea unei pro-
bleme se poate face prin descompunerea ei n cazuri de dimensiune mai mic a,
rezolvarea acestora dupa acelasi principiu, apoi combinarea rezultatelor lor.
Deseori algoritmii de acest tip se scriu ca recursiv (datorit a naturii lor), iar
determinarea complexit at ii se face prin rezolvarea unei ecuat ii recursive, a
c arei solut ii se poate da de multe ori pe baza Teoremei centrale.
Un exemplu important de algoritm de tip divide et Impera este Quicksort.
Problemele de la sf arsitul capitolului dau si alte exemple ale utilit at ii metodei.
2
Se poate ar ata c a:
2n
n+
1
2
e
n
e
(12n+1)
1
< n! <
2n
n+
1
2
e
n
e
(12n)
1
80
8.6 Exercit ii (rezolvarile la pagina 162)
1. Baz anduv a pe observat ia c a mutarea din mijloc se stie, scriet i un
algoritm iterativ pentru problema turnurilor din Hanoi, pun and mereu
mijloacele intervalelor obt inute prinnjum at at irentr-un sir cu num arul
cunoscut de mut ari.
2. Av and la intrare un sir ordonat cresc ator, s a se scrie un algoritm de
tip Divide et Impera pentru g asirea pozit iei unui element de valoare
dat a x, dac a el exist a. Se va folosi metodanjum at at irii intervalului dat
de num arul de elemente al sirului. Care este complexitatea c aut arii?
3. Rezolvat i aceeasi problem a prin c autare secvent ial a (testarea pe r and
a elementelor). Care este n acest caz complexitatea?
4. Demonstrat i c a timpul de execut ie al algoritmului QuickSort, n cazul
unui vector cu toate elementele egale, este (nlog n).
5. Complexitatea algoritmului QuickSort este mare din cauz a c a n cazuri
defavorabile, partit ionarea se face cu un singur element ntr-una din
partit ii. Rescriet i algoritmul de partit ionare, lu and ca element de se-
parare nu primul element, ci valoarea din mijloc ntre primul element,
ultimul si cel aat pe pozit ia din mijloc.
81
82
Capitolul 9
Sortare si statistici de ordine
9.1 Obiective
din sirul
sortat.
In cazul nostru mediana este 5.
Ce reprezint a minimul si maximul din perspectiva statisticilor de ordine?
Minimul este prima component a n ordine statistic a a unui sir. Maximul este
a n-a component a n ordine statistic a.
9.3 Determinarea simultana a minimului si a
maximului
MinMax(x, n)
dac a n mod 2 = 0 atunci
dac a x(1) < x(2) atunci
min = x(1)
max = x(2)
altfel
min = x(2)
max = x(1)
sf arsit dac a
k = 3
altfel
min = x(1)
max = x(1)
k=2
sf arsit dac a
pentru i = k, n 1, 2
dac a x(i) < x(i + 1) atunci
mic = x(i)
mare = x(i + 1)
altfel
mic = x(i + 1)
mare = x(i)
sf arsit dac a
dac a mic < min atunci
min = mic
sf arsit dac a
84
dac a mare > max atunci
max = mare
sf arsit dac a
sf arsit pentru
scrie( minimul este , min )
scrie( maximul este , max )
Return
Num arul de comparat ii ntre elemente necesare n determinarea indepen-
dent a a min si max este 2(n1) (prin dou a parcurgeri ale sirului), n schimb
pentru determinarea simultan a a min si max avem nevoie de 3 n/2| 2
comparat ii (demonstrat i acest lucru). Suger am cititorului s a execute algo-
ritmul pentru intrarea x = (1, 2, 3, 4, 5, 6, 85, 2).
9.4 Gasirea celor mai mici doua elemente dintr
un sir
Ideea algoritmului prezentat mai jos este urm atoarea: se compar a ele-
mentele 1 cu 2, 3 cu 4, etc; pentru ecare pereche comparat a se determin a
cel mai mic. Aceste elemente c astig atoare se vor compara la r andul lor pe
perechi adiacente, ca mai sus. C and r am ane un singur element, acesta este
minimul sirului. Atas am acestor operat ii un arbore binar (posibil nestrict)
echilibrat, construit n felul urm ator: exist a n noduri terminale (frunze), e-
care cont in and drept informat ie c ate un element din sir; un nod neterminal
are drept valoare minimul din cei doi i (gura 9.4).
4
4
6
7 6 4 5
1
1
2 1
3 2 1
(a) Arborele de comparat ii pentru
vectorul (7, 6, 4, 5, 2, 3, 1)
4
4
6
7 6 4 5
1
1
2 1
1 2 3
(b) Arborele de comparat ii pentru
vectorul (7, 6, 4, 5, 2, 1, 3)
Figura 9.1: Exemple de arbori construit i conform strategiei de mai sus.
85
Evident c a pentru ecare nod neterminal, informat ia sa coincide cu a unui
descendent al s au.
In cadrul acestui algoritm vom folosi termenul nvins
n exprimarea x este nvins de y dac a x > y (deoarece se caut a mini-
mul). Pentru determinarea celui de al doilea minim trebuie s a determin am
cel mai mic element din vectorul init ial nvins de minim: n exemplele
date este 2, nvins de 1. Pentru aceasta vom considera informat ia din
cei doi descendent i ai r ad acinii, n ambele exemple date ind 4 si 1. 4 este
cel mai mic element din jum atatea st ang a a sirului (este descendent st ang
al r ad acinii) si va trebui s a c aut am n jum atatea dreapt a a sirului cel mai
mic num ar, nvins de r ad acin a; acest lucru se face (n exemplele date) co-
bor and n subarborele drept spre frunze. Se compar a toate elementele pe
care informat ia din r ad acin a lea dep asit cu minimul din jum atatea st ang a
(n cazul nostru 4); cobor area se termin a atunci c and e se ajunge la frunze
(cazul 9.1(b)), e este evident c a nu mai are sens cobor area (cazul 9.1(a)).
h=0
_
n
2
h+1
_
O(h) = O
_
_
n
log
2
n
h=0
h
2
h
_
_
Dar
log
2
n
h=0
h
2
h
h=0
h
2
h
=
1/2
(1 1/2)
2
= 2
Deci timpul de execut ie pentru algoritmul ConstruiesteHeap este O(n).
Folosim cei doi algoritmi de mai sus pentru sortare n modul urm ator:
HeapSort(a, n)
ConstruiesteHeap(a, n)
pentru i = n, 2, 1
a(1) a(i)
Heapify(a, i 1, 1)
sf arsit pentru
Return
Sortarea cu HeapSort se face cu complexitatea O(n) + nO(log
2
n) =
O(nlog
2
n). Deoarece sortatea folosind comparat ii are complexitatea infe-
rioar a (nlog
2
n) (sect iunea 8.4), rezult a c a algoritmul Heapsort are com-
plexitatea (nlog n).
90
2
14 8 7
3
4
1
16 10 9 i
(a) i = 5
2
14 8 7
3
4
1
16 10 9
i
(b) i = 4
2 7
3
4
1
16 10 9 14
8
i
(c) i = 3
2 7
10
4
1
16 3 9 14
8
i
(d) i = 2
2 1
3
4
16
7 10 9 14
8
i
(e) i = 1
1
3
16
14
7 10 9 8
4 2
(f) Heap-ul dup a terminarea algorit-
mului
Figura 9.3: Obt inerea unui maxheap din sirul (4, 1, 3, 2, 16, 9, 10, 14, 8, 7).
91
Exemplu: e sirul: a = (4, 1, 3, 2, 10, 7, 8, 9, 6, 5). Dupa apelul procedurii
ConstruiesteHeap(a, 10) se obt ine heap-ul din Figura 9.5(a). Pentru apelurile
Heapify(a, i 1, 1) (i = n, n 1, . . . , 2) evolut ia este dat a n Figurile 9.5(b)-
9.5(j) (sau pus n evident a prin detasare elementele care nu vor mai face
parte din heap).
Rezultatul sort arii sirului a este: a = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10).
Heapsort este un excelent algoritm de sortare, dar o implementare bun a
a QuickSortului duce la sort ari mai rapide. Heapul este ns a foarte util n
t inerea n evident a dinamic a a cozilor de priorit at i unde o complexitate de
n care sar putea obt ine printrun algoritm cu insert ie este nlocuit a cu o
complexitate de log n p astr and coada ntrun heap.
9.7 Algoritmi de sortare n timp liniar
Exist a algoritmi de sortare a c aror complexitate este mai mic a dec at cea
teoretic a de (nlog
2
n), dar pentru situat ii speciale ale sirului. Astfel, dac a
sirul este constituit din numere ntregi pozitive (sau m acar ntregi), sau dac a
ele sunt numere distribuite uniformntrun interval, sau lund n considerare
cifrele numerelor din sir se pot da diferit i algoritmi de complexitate liniar a
pentru sortare.
9.7.1 Algoritmul sortarii prin numarare (CountSort)
Un astfel de algoritm este algoritmul de sortare prin num arare numit
CountSort. Fie (x(i))
i=1,n
un sir de numere naturale strict pozitive si k
maximul acestui sir. Sortarea prin num arare const an g asirea a c ate elemente
sunt mai mici dec at x(i) (pentru ecare i); n acest fel vom sti pe ce pozit ie
trebuie s a se ae x(i) n sirul sortat (dac a sunt m elemente mai mici dec at
x(i), atunci el ar trebui s a se ae pe pozit ia m + 1 n sirul sortat).
Consider am sirul init ial x = (x(1), x(2), . . . , x(n)); y = (y(1), y(2), . . . , y(n))
va sirul sortat, iar c = (c(1), c(2), . . . c(k)) este un sir ajut ator.
CountSort(x, n, y, k)
pentru i = 1, k
c(i) = 0
sf arsit pentru
pentru j = 1, n
c(x(j)) = c(x(j)) + 1
sf arsit pentru
pentru i = 2, k
c(i) = c(i) +c(i 1)
92
6
2 4 1
8 9
5 3 7
10
(a) Dup a apelul proce-
durii Heapify
4
2 1 10
8 6
5 3 7
9
(b) i = 10
4
2 9 10
7 6
5 3 1
8
(c) i = 9
4
8 9 10
3 6
5 2 1
7
(d) i = 8
4
8 9 10
3 5
2 7 1
6
(e) i = 7
1
8 9 10
3 4
2 7 6
5
(f) i = 6
1
8 9 10
3 2
5 7 6
4
(g) i = 5
4
8 9 10
1 2
5 7 6
3
(h) i = 4
4
8 9 10
3 1
5 7 6
2
(i) i = 3
4
8 9 10
3 2
5 7 6
1
(j) i = 2
Figura 9.5: Evolut ia sirului si a heapului n subalgoritmul Heapsort.
93
sf arsit pentru
pentru j = n, 1, 1
y(c(x(j))) = x(j)
c(x(j)) = c(x(j)) 1
sf arsit pentru
Return
Exemplu: x = (3, 6, 4, 1, 3, 4, 1, 4), k = 6.
- elementele lui c sunt init ializate cu 0:
c = (0, 0, 0, 0, 0, 0)
- pentru i de la 1 la k, pe pozit ia i din c obt inem num arul de elemente
egale cu i n sirul x:
c = (2, 0, 2, 3, 0, 1)
- pentru i = 2, k, pe pozit ia i a sirului c se obt ine c ate elemente mai mici
sau egale cu i sunt n sirul x:
c = (2, 2, 4, 7, 7, 8)
- pentru j = n, 1, cu pasul -1, se a a componentele sirului y sortat:
y = (1, 1, 3, 3, 4, 4, 4, 4, 6)
Complexitatea algoritmului CountSort este (n+k). Dac a k = O(n) (adic a
exist a o constant a c astfel nc at pentru orice n sucient de mare, s a avem
k < cn), atunci complexitatea algoritmului de sortare prin num arare este
(n).
9.7.2 Sortare pe baza cifrelor
S a presupunem c a avem un sir de numere naturale, av and toate acelasi
num ar d de cifre (dac a nu, atunci un num ar se poate completa cu zerouri
nesemnicative p an a c and atinge num arul maxim de cifre din sir). Se poate
face ordonarea sirului de numere n felul urm ator: se porneste de la cifra cea
mai put in semnicativ a (ultima cifr a) si se sorteaz a elementele pe baza aces-
tei informat ii, obt in anduse o alt a ordine (un alt sir). Se porneste de al acest
ultim sir generat si se sorteaz a elementele dup a urm atoarea cifr a mai put in
semnicativ a (penultima cifr a), pentru care se face sortarea elementelor; si
asa mai departe, n nal f ac anduse sortarea dup a cea mai semnicativ a cifr a
(prima cifr a). Esent ial este ca dac a sortarea se face dup a cifra i (numerotarea
94
cifrelor o consider am de la st anga spre dreapta, de la cifra cea mai semni-
cativ a la cea cea mai put in semnicativ a), atunci se pleac a de la ordinea
obt inut a anterior pentru cifra i +1 (1 i < d); n al doilea r and, algoritmul
care este folosit pentru sortarea cifrelor trebuie s a aibe urm atoarea proprie-
tate: dac a ntrun sir x = (x(1), . . . , x(n)) avem c a x(i) = x(j) si i < j, prin
sortare se ajunge ca x(i) s a e repartizat pe pozit ia i
, x(j) s a e repartizat
pe pozit ia j
, iar i
< j
respect a C.
In caz contrar se ncearc a s a se determine c at de departe
este solut ia g asit a de algoritm fat a de solut ia c autat a.
Complexitate solut iei Greedy este dat a de complexitatea select iei valorii
la ecare pas si de num arul de select ii f acut de c atre algoritm.
In general,
metodele de tip Greedy sunt metode de complexitate polinomial a mic a, ceea
ce este o justicare pentru utilitatea metodei.
Exemplifc am metoda anterioar a prin c ateva probleme clasice.
10.3 Submult imi de suma maxima
Enunt ul problemei: Dac a x = (x(i), i = 1, n) reprezint a o mult ime de
elemente atunci s a se determine submult imea y = (y(i), i = 1, k) de sum a
maxim a.
Date de intrare: n - dimensiunea vectorului; x = (x(i), i = 1, n), mult imea
de elemente;
100
Date de iesire: k - num arul de elemente al submult imii y = (y(i), i = 1, k)
- submult imea de elemente.
Problema anterioar a este o problem a clasic a de optimizare care se rezolv a
prin Greedy. Submult imea c autat a este o solut ie a problemei de optimizare
max
_
yY
y[ ,= Y X
_
Simplitatea problemei de optimizare ofer a un criteriu de selet ie foarte simplu
bazat pe observat iile:
1. dac an mult imea x sunt numere pozitive, ad augarea unuia la submult imea
y conduce la cresterea sumei; g asim astfel submult imea y format a din
toate elementele pozitive;
2. n cazul n care toate elementele sunt negative, submult imea y este
format a cu cel mai mare element.
Ca atare, la ecare pas alegem n y elementele pozitive. Dac a nu sunt,
atunci alegem n y elementul maximal.
SumaMax(n, x, k, y)
k = 0
pentru i = 1, n
dac a x(i) 0 atunci
k = k + 1
y(k) = x(i)
sf arsit dac a
sf arsit pentru
dac a k = 0 atunci
max = x(1)
pentru i = 2, n
dac a x(i) > max atunci
max = x(i)
sf arsit dac a
sf arsit pentru
k = 1
y(k) = max
sf arsit dac a
Return
Se observ a c a ecare din cele n select ii are complexitate (1), g asind n nal
o complexitate pentru algoritm de (n).
101
Teorema 2 (Corectitudine). Submult imea y determinat a de c atre algoritm
are suma elementelor maxim a fat a de toate submult imile lui x.
Demonstrat ie. Not am sum(x) suma elementelor din x. Fie z submult imea
de sum a maxim a. Vom ar ata c a y = z trat and cele dou a cazuri.
1.
In x nu sunt elemente pozitive. Atunci sum(z) z(1) max x(i), i = 1, n =
sum(y); din proprietatea lui z rezult a sum(z) = sum(y) si deci y este
submult ime de sum a maxim a.
2.
In x sunt elemente pozitive. Atunci urm atoarele armat ii conduc la
egalitatea y = z:
(a) z nu cont ine elemente negative. Dac a z cont ine elementul a ne-
gativ, atunci sum(z) = sum(z a) + a < sum(z a) fals,
pentru c a z este de sum a maximal a;
(b) z cont ine toate elementele pozitive. Dac a z nu cont ine elementul
strict pozitiv a atunci sum(z) < sum(z +a) fals.
R am ane c a z nu cont ine elemente negative si cont ine toate pozitivele,
deci y = z
10.4 Arborele Human
Enunt ul problemei: dac a S = s
1
, s
2
, . . . , s
n
este o mult ime de semnale
si p = (p(i), i = 1, n) este vectorul de probabilitate asociat lui S, atunci s a se
determine codul de lugime optim a asociat lui S.
Date de intrare: n - num arul de semnale, p = (p(i), i = 1, n) - vectorul de
probabilit at i.
Date de iesire: codul optim reprezentat sub form a arborescent a.
Un exemplu de cod care simuleaz a optimalitatea este alfabetul Morse.
O caracteristic a a acestui cod este aceea c a simbolurile cele mai probabile
sunt codicate cu mai put ine caractere, astfel nc at costul transmisiei s a e
c at mai mic.
Inainte de a da rezolvarea problemei, este bine s a facem o
prezentare a c atorva not iuni de teoria codurilor.
Un cod binar este o aplicat ie injectiv a : S 0, 1
+
. Lungimea me-
die a codului n funct ie de sistemul de probabilit at i este denit a de L() =
n
i=1
[(s
i
)[p(i) ([a[ este num arul de caractere a lui a). Un cod este op-
tim dac a minimizeaz a lungimea medie. Dac a : S 0, 1
+
este un cod
instantaneu, atunci arborele m-ar asociat se noteaz a cu T
si veric a:
102
- are at atea frunze c ate semnale are S;
- drumul n arbore de la r ad acin a la frunz a s S d a codicarea (s)
prin concatenarea marcajelor muchiilor.
Lungimea medie a unui cod poate transportat a ntro lungime medie a
arborelui asociat, dat a de L() =
n
i=1
[(s
i
)[p(i) =
n
i=1
niv
T
(s
i
)p(i) =
L(T
).
Numim arbore Human asociat sistemului de numere reale p = (p(i), i =
1, n) arborele ce minimizeaz a L(T) =
n
i=1
niv
T
(s
i
)p(i).
Vom lucra cu structuri arborescente reprezentate nl ant uit n care n
c ampul de informat ie avem probabilitatea sau frecvent a simbolului.
P an a n acest moment nu am spus nimic despre modul de aplicare al
stretegiei Greedy. R am ane armat ia f acut a init ial c a semnalele cele mai
probabile sunt codicate cu c at mai put ine caractere.
Algoritmul lui Human construieste codul optim prelucr and o p adure
dup a regulile:
- init ial p adurea este format a din v arfuri izolate reprezent and semnalele.
- se repet a o execut ie dat a de:
1. se selecteaz a arborii p adurii av and informat ia cea mai mic a;
2. se conecteaz a cei doi arbori alesi ntrunul singur printro r ad acin a
comun a av and informat ia suma informat iilor din arbori
Proceura Human determin a arbore minim.
Human(n, s, p, rad)
pentru i = 1, n
s(i) LIBERELIBERE este zona din care se fac aloc ari de memorie
LS(s(i)) =
LD(s(i)) =
INFO(s(i)) = p(i)
sf arsit pentru
Sort(n, s)
pentru i = n, 2, 1
x LIBERE
LS(x) = s(i)
LD(x) = s(i 1)
INFO(x) = p(i) +p(i 1)
j = i 1
pentru j > 0 si INFO(x) > INFO(s(j))
103
s(j + 1) = s(j)
j = j 1
sf arsit pentru
s(j + 1) = x
sf arsit pentru
rad = s(1)
Return
n
i=1
i 1 = n(n 1)/2 = (n
2
) comparat ii.
Rezult a complexitatea din enunt .
Teorema 4 (Corectitudine). Algoritmul Human genereaz a un cod optim
n raport cu probabilit at ile p = (p(i), i = 1, n).
Demonstrat ie. Vom folosi n demonstrat ie urm atoarele notat ii:
H = H(p
1
, . . . , p
n
) - arborele dat de algoritmul lui Human
T = T(p
1
, . . . , p
n
) - arborele optim, unde p(i) = p
i
, i = 1, n.
Despre arborele optim se poate ar ata:
p
i
< p
j
rezult a niv
T
(s
i
) > niv
T
(s
j
)
exist a un arbore optim n care cele mai put in probabile semnale sunt
frat i.
S a presupunem c a s
i
si s
j
sunt semnalele cu probbabilitatea cea mai mic a si
c a prin unirea celor dou a semnale se creeaz a un nou semnal notat s
i,j
.
Algoritmul Human construieste arborele binar dup a regula recursiv a
dat a de gura 10.1. Avem urm atorul calcul de lungime:
L(H) =
n
i=1
niv(s
i
) =
n2
i=1
niv(s
i
)p(i) +niv(s
n1
)p(n 1) +niv(s
n
)p(n)
104
s
n1
s
1
s
n
H( ,..., ) s
1
s
n1,n
H( ,..., )
s
n
=>
Figura 10.1: Crearea unui nod pe baza semnalelor cele mai put in probabile
si deoarece niv(s
n1
) = niv(s
n
) rezult a c a:
L(H) =
n2
i=1
niv(s
i
)p(i) + (p(n 1) +p(n))niv(s
n1
) 1 +
+ p(n 1) +p(n) =
=
n2
i=1
niv(s
i
))p(i) +p(n 1, n)niv(s
n,n1
) +p(n 1) +p(n)
g asindn nal L(H(p(1), . . . , p(n))) = L(H(p(1), . . . , p(n1)+p(n)))+p(n
1) +p(n)
Printrun calcul analog se arat a c a si arborele optim ce are pe s
n=1
si s
n
veric a:
L(T(p(1), . . . , p(n))) = L(T(p(1), . . . , p(n 1) +p(n))) +p(n 1) +p(n).
Demonstrat ia optimalit at ii se va face prin induct ie dup a n.
Pentru n = 2 algoritmul ne ofer a H(p(1), p(2)) care codic a pe s
1
cu 0 si
pe s
2
cu 1, ceea ce nseamn a c a este un cod optim.
S a presupunem c a avem proprietatea adev arat a pentru n semnale si anume
codul Human asociat semnalelor s
1
, . . . , s
n
este optim.
Fie p = (p(i), i = 1, n+1) un sistem cu n+1 probabilit at i n care p(n1)
si p(n 2) sunt cele mai mici dou a numere din sirul p. Aplic and formulele
g asite anterior obt inem:
L(H(p(1), . . . , p(n), p(n + 1))) = L(H(p(1), . . . , p(n) +p(n + 1)) +p(n) +p(n + 1))
L(T(p(1), . . . , p(n), p(n + 1))) = L(T(p(1), . . . , p(n) +p(n + 1)) +p(n) +p(n + 1))
Pentru c a arborele Human codic a n semnale optim vom g asi:
L(T(p(1), . . . , p(n) +p(n + 1))) L(H(p(1), . . . , p(n) +p(n + 1)))
105
Din relat iile de mai sus vom g asi:
L(T(p(1), . . . , p(n) +p(n + 1))) +p(n) +p(n + 1) L(H(p(1), . . . , p(n)
+p(n + 1))) +p(n) +p(n + 1)
si deci L(T(p(1), . . . , p(n), p(n + 1))) L(H(p(1), . . . , p(n), p(n + 1))) Din
optimalitatea lui T vom g asi:
L(T(p(1), . . . , p(n), p(n + 1))) = L(H(p(1), . . . , p(n), p(n + 1)))
deci H este un arbore optim.
10.5 Interclasare optimala
Enunt ul problemei: D anduse o mult ime de vectori sortat i cresc ator s a
se elaboreze un algoritm care determin a interclasarea acestora cu num arul
minim de comparat ii.
Date de intrare: n - num arul de vectori, nr = (nr(i), i = 1, n) - num arul
de elemente din ecare vector, x(i) = (x(i, j), j = 1, nr(i)) sirul de vectori.
Date de iesire: y = (y(i), i = 1, nr(1) + +nr(n)), vectorul interclasat.
S a presupunem c a interclasarea a doi vectori se face prin algoritmul de
interclasare direct a. Dac a dimensiunile vectorilor sunt m, respectiv n atunci
num arul de comparat ii este cel mult m + n 1.
In general aceast a inter-
clasare nu este una optim a dar facem presupunerea c a orice doi vectori se
interclaseaz a folosind interclasarea direct a.
In funct ie de modul de intercla-
sare al vectorilor de interclasare se obt in diferite solut ii cu num ar distinct de
comparat ii. Este deci esent ial s a g asim o ordine care conduce c atre num arul
minim de comparat ii.
Vom nota x+y vectorul obt inut prin interclasarea lui x cu y. Dac a avem
4 vectori x, y, z, t cu respectiv 10, 20, 30 si 40 de elemente atunci:
interclasarea ((x+y)+z)+t se face cu (10+20-1)+(30+30-1)+(60+40-
1)=187 comparat ii
inteclasarea ((z +t) +y) +x se face cu (30+40-1)+(70+20-1)+(90+10-
1)=257 comparat ii
deci prima strategie este mai bun a dec at a doua (de fapt, este chiar cea
optim a). Din acest exemplu se observ a c a maxim a 40 se reg aseste n toate
interclas arile ce se efectueaz a conduc and al un num ar mare de comparat ii.
Idea ar ca vectorii cu dimensiuni mici s a se se interclaseze prima dat a astfel
106
nc at aceste valori mici s a apar a n sumele de interclasare. Deci la ecare pas
vom selecta pentru interclasare vectorii de dimensiune minim a.
Pentru ca select ia s a se fac a c at mai usor psstr am vectorii n matricea x
astfel nc at vectorul nr s a e sortat descresc ator.
In acest caz se selecteaz a
ultimii 2 vectori din matricea x. Dup a realizarea interclas arii noul vector se
insereaz a nmatricea x folosind diferite tehnici: insert ia direct a sau insert ia
binar a. Se repet a procesul p an a c and r am ane un singur vector.
InterOpt(n, nr, x, z)
Sortare(n, nr, x)
pentru i = n 1, 1, 1
Inter(nr(i + 1), x(i + 1), nr(i), x(i), y)
n1 = nr(i)
n2 = nr(i + 1)
j = i 1
c at timp j > 0 si n(j) > n1 +n2
pentru k = 1, nr(j)
x(j + 1, k) = x(j, k)
sf arsit pentru
nr(j + 1) = nr(j)
j = j 1
sf arsit c at timp
pentru k = 1, n1 +n2
x(j + 1, k) = y(k)
sf arsit pentru
nr(j + 1) = n1 +n2
sf arsit pentru
Return
n
i=1
nr(i)
niv(i) n + 1 unde niv(i) este nivelul n T al vectorului x(i)
Teorema 5 (Corectitudine). Algoritmul InterOpt determin a interclasarea
vectorilor x(i), i = 1, n cu num ar minim de comparat ii realizate din inter-
clas arile directe.
Demonstrat ie. Se observ a c a arborele asociat unei strategii de interclasare ete
arborele Human asociat numerelor nr(1), . . . , , nr(n). Algoritmul anterior
repet a modul de construct ie al arborelui Human deci suma
n
i=1
nr(i)
niv(i) este minim a si implicit L(T) este minim. Rezult a c a strategia de
interclasare este optim a.
108
Teorema 6 (Complexitate). Dac a L este num arul de comparat ii rezultat
din interclas arile directe, atunci algoritmul InterOpt are complexitatea (L+
n
2
).
Demonstrat ie. Complexitatea algoritmului este dat a de num arul de comparat ii
f acut de interclas arile directe si de num arul de comparat ii dat de p astrarea
structurii x.
In primul caz num arul este n. Pentru cel de al doilea caz se
observ a c a inserarea direct a foloseste cel mult i 1 comparat ii pentru ou-
nerea sirului y n structura x. G asim un num ar total de
n
i=2
(i 1) = (n
2
)
comparat ii.
Dac a se utilizeaz a o inserare binar a n structura x atunci complexitatea
algoritmului devine (L +nlog n).
10.6 Rezumat
Metoda Greedy nseamn a construirea pas cu pas a solut iei, prin alegerea
componentelor pe baza unei strategii deduse din enunt ul problemei. Spre de-
osebire de metoda Backtracking, nu se revine asupra unei decizii. Ea poate
folosit a si pentru elaborarea unor algoritmi euristici (care nu determin a op-
timul, sau pentru care o demonstrat ie de corectitudine nu este dat a). Pentru
ecare rezolvare greedy trebuie s a se ncerce justicarea prin metode mate-
matice a optimalit at ii solut iei.
10.7 Exercit ii (rezolvarile la pagina 99)
1. Dac a x = (x(i), i = 1, m), y = (y(i), i = 1, n) reprezint a dou a mult imi
de elemente, atunci s a se determine mult imea intersect ie z = (z(i), i =
1, k).
2. D anduse n obiecte de cost c = (c(i), i = 1, n) cu greutatea g =
(g(i), i = 1, n) si un rucsac de capacitate maxim a G, s a se elaboreze un
algoritm de umplere a rucsacului de cost maxim. Un obiect poate pus
n rucsac ntrun anumit procent (problema continu a a rucsacului).
3.
Intro sal a, ntro zi trebuie planicate n spectacole. Pentru ecare
spectacol se cunoaste intervalul n care se desf asoar a: [st, sf). Se cere
s a se planice un num ar maxim de spectacole astfel nc at s a nu se
suprapun a..
109
4. Se dau n numere ntregi nenule b
1
, . . . , b
n
si m numere ntregi nenule
a
1
, . . . a
m
, n m. S a se determine o submult ime a mult imii B =
b
1
, . . . , b
n
care s a maximizeze valoarea expresiei:
E = a
1
x
1
+a
2
x
2
+ +a
m
x
m
unde x
i
B..
5. O stat ie de servire trebuie s a satisfac a cererile a n client i. Timpul de
servire pentru ecare client este cunoscut: pentru clientul i timpul este
t
i
. S a se minimizeze timpul total de asteptare
T =
n
i=1
(timpul de asteptare pentru clientul i)
110
Capitolul 11
Programare dinamic a
11.1 Obiective
k=1
P(k)P(n k) dac a n 2
(11.1)
Numerele dente de (11.1) se numesc numerele lui Catalan si se arat a c a
P(n) =
1
n
C
n1
2n2
, de unde P(n) = (
4
n
n
2
). Num arul de solut ii este exponent ial,
deci ar o strategie slab a.
Primul pasn schema general a a metodei program arii dinamice este dat de
caracterizarea unei solut ii optimale. Pentru problema noastr a descrierea este
f acut a n continuare. Vom face urm atoarea convent ie de notare: matricea
obt inut a n urma procesului de evaluare a produsului A
i
A
i+1
. . . A
j
se va
nota cu A
i...j
. O parantezare optim a a produsului A
1
. . .A
n
mparte produsul
ntre A
k
si A
k+1
pentru un anumit k din intervalul 1 . . . n. Aceasta nseamn a
c a pentru o valoare a lui k, mai nt ai calcul am matricele A
1...k
si A
k+1...n
si apoi
le nmult im pentru a obt ine rezultatul nal A
1...n
. Costul acestei parantez ari
optime este dat de suma costurilor calculului pentru matricele A
1...k
, A
k+1...n
si A
1...n
. Observat ia care trebuie f acut a este c a: parantezarea subsirului
prex A
1
. . . A
k
n cadrul parantez arii optime a produslui A
1
. . . A
n
este o
parantezare optim a pentru A
1
. . . A
k
, pentru c a altfel, dac a am presupune
c a mai exist a o metod a de parantezare mai put in costisitoare a lui A
1
. . . A
k
ar contrazice faptul c a parantezarea pentru A
1
. . . A
n
este optim a. Aceast a
observat ie este valabil a si pentru parantezara lui A
k+1
. . . A
n
. Prin urmare, o
solut ie optim a a unei instant e a unei probleme cont ine solut ii optime pentru
instant e ale subproblemelor.
Al doilea pas n aplicarea metodei program arii dinamice este dat de de-
nirea valorii unei solut ii optime n mod recursiv, n funct ie de solut iile optime
ale subproblemelor.
In cazul problemei nmult irii sirului de matrice, o sub-
problem a const a n determinarea costului minim al unei parantez ari a sirului
A
i
A
i+1
A
j
, pentru 1 i j n. Fie m(i, j) num arul minim denmult iri
scalare necesare pentru a calcula matricea A
i...j
; costul modalit at ilor optime
de calcul al lui A
1...n
va m(1, n). Denit ia recursiv a a lui m(i, j) este dat a
de formula (11.2)
m(i, j) =
_
0 dac a i = j
min
ik<j
m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
dac a i < j
(11.2)
Valorile m(i, j) exprim a costul solut iilor optime ale subproblemelor. Pen-
tru a putea urm ari modul de construct ie a slout iei optime, s a denim s(i, j)
care va cont ine valoarea k pentru care mp art irea produsului A
i
. . . A
j
pro-
duce o parantezare optim a. Aceasta nseamn a c a s(i, j) este egal cu valoarea
lui k pentru care m(i, j) = m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
.
114
In tabelul 11.2 de mai jos este descris a funct ionarea algoritmului pentru
un sir de n = 6 matrici av and dimensiunile date n tabelul 11.1.
Matrice Dimensiune
A
1
30 35
A
2
35 15
A
3
15 5
A
4
5 10
A
5
10 20
A
6
20 25
Tabelul 11.1: Dimensiunile matricelor care se nmult esc
1 2 3 4 5 6 1 2 3 4 5 6
0 15750 7875 9375 11875 15125 0 1 1 3 3 3
0 0 2625 4375 7125 10500 0 0 2 3 3 3
0 0 0 750 2500 5375 0 0 0 3 3 3
0 0 0 0 1000 3500 0 0 0 0 4 5
0 0 0 0 0 5000 0 0 0 0 0 5
0 0 0 0 0 0 0 0 0 0 0 0
Tabelul 11.2: Evolut ia algoritmului pentru matricile din tabelul 11.1.
In
partea st ang a apare matricea m, n partea dreapt a matricea s.
i=1
n
j=i
R(i, j) =
n
3
n
3
. (Indicat ie:
n
i=1
i
2
=
n(n+1)(2n+1)
6
).
4. Se d a o matrice subdiagonal a. Se consider a toate sumele n care se
adun a elementele de pe ecare linie aate sub elementul adunat anterior
sau sub-si-la-dreapta. Se cere un algoritm care g aseste suma maxim a.
Exemplu:
5
2 3
8 1 2
5 9 3 4
Suma maxim a este S = 5 + 2 + 8 + 9.
5. Folosind rezultatele lui InmultireMatrici s a se descrie un algoritm care
realizeaz a nmult irea matricilor n ordine optim a.
120
Capitolul 12
Teste de autoevaluare
1. Algoritmi de sortare prin metoda Divide et impera.
2. Folosind un subalgoritm pentru nmult irea matricilor s a se scrie algo-
ritmul care ridic a la puterea k o matrice p atratic a de ordinul n.
3. D andu-se parcurgerile n preordine A, B, C, D, E, F, G si n inordine
C, B, E, D, A, G, F s a se deseneze arborele binar corespunz ator.
Solut ii
1. (Din ociu: 1p)
Metoda presupune parcurgerea a trei pasi:
a) mp art irea datelor n mai multe p art i;
b) rezolvarea (de obicei recursiv a) a problemei pe ecare bucat a
de date;
c) combinarea rezultatelor part iale n rezultatul nal.
(1p)
Sortarea prin interclasare presupune:
a) mp art irea sirului init ial n dou a p art i;
b) sortarea ec arei jum at at i;
c) interclasarea buc at ilor sortate.
MergeSort(a, p, q)
dac a p q atunci
Return
sf arsit dac a
121
r =
_
p+q
2
MERGESORT(a, p, r)
MERGESORT(a, r + 1, q)
Interclasare(a, p, r, q)
Return
(1p)
Interclasare(a, p, r, q)
i = p
j = r + 1
k = 0
repet a
k = k + 1
dac a a(i) < a(j) atunci
b(k) = a(i)
i = i + 1
altfel
b(k) = a(j)
j = j + 1
sf arsit dac a
p an a c and i > r sau j > q
pentru il = i, r
k = k + 1
b(k) = a(il)
sf arsit pentru
pentru jl = j, q
k = k + 1
b(k) = a(jl)
sf arsit pentru
k = 0
pentru i = p, q
k = k + 1
a(i) = b(k)
sf arsit pentru
Return
(2p)
Apelarea se face:
Start Sortare1
citeste( n, (a(i), i = 1, n) )
MERGESORT(a, 1, n)
122
scrie( (a(i), i = 1, n) )
Stop
Complexitatea rezult a din:
T(n) = 2T
_
n
2
_
+a n
unde a este o constant a. Din teorema central a (pagina 72) onbt inem
T(n) = (nlog n). (1p)
Alt a metod a este Quicksort (n practic a, cel mai bun algoritm de sor-
tare):
Quicksort(a, p, q)
dac a p < q atunci
Partitionare(a, p, q, r)
Quicksort(a, p, r)
Quicksort(a, r + 1, q)
sf arsit dac a
Return
(1p)
unde
Partitionare(a, p, q, r)
el = a(p)
i = p 1
j = q + 1
repet a
repet a
i = i + 1
p an a c and a(i) el
repet a
j = j 1
p an a c and a(j) el
dac a i < j atunci
a(i) a(j)
altfel
r = j
sf arsit dac a
p an a c and i j
Return
(2p)
123
Se apeleaz a ca si cel alalt.
Complexitatea este (n
2
), dar n cazul (frecvent) al mp art irii propor-
t ionale a sirului avem (nlog n). Se pot face mbun at at iri prin alegerea
aleatoare al lui el (elementul pivot). (1p)
2. Vom scrie doi subalgoritmi: unul pentru inmult irea a dou a matrice
p atratice si altul pentru ridicarea la putere a unei matrici.
Din ociu (1p).
InmultireMatrici(a, b, c, n)
pentru i = 1, n
pentru j = 1, n
c(i, j) = 0
pentru k = 1, n
c(i, j) = c(i, j) +a(i, k) b(k, j)
sf arsit pentru
sf arsit pentru
sf arsit pentru
Return
(3p)
PutereMatrice(a, n, k, c)
pentru i = 1, n
pentru j = 1, n
b(i, j) = a(i, j)
sf arsit pentru
sf arsit pentru
pentru p = 2, k
InmultireMatrici(a, n, b, c)
pentru i = 1, n
pentru j = 1, n
b(i, j) = c(i, j)
sf arsit pentru
sf arsit pentru
sf arsit pentru
Return
(4p)
Subalgoritmul PutereMatrice se apeleaz a n felul urm ator:
Start RidicareLaPutere
citeste( k, n, ((a(i, j), j = 1, n), i = 1, n) )
PutereMatrice(a, n, k, c)
124
scrie( ((c(i, j), j = 1, n), i = 1, n) )
Stop
(1p)
Complexitatea este (n
3
k). (1p)
Observat ie: Prin algoritmul ridic arii la putere prezentat n capitolul
5, problema 3, se poate scrie un algoritm de complexitate (n
3
log k).
Utiliz and un subalgoritm care s a efectueze nmult irea a dou a matrce n
timp (n
log
2
7
) (algoritmul lui Strassen, vezi [1]), se ajunge la un algo-
ritm de complexitate
_
n
log
2
7
log k
_
(sau chiar (n
2.376
log k), conform
aceleiasi surse bibliograce).
3. Din ociu (1p). Arborele este dat n gura 12.1. Rat ionamentul prin
care se construieste arborele se poate face dup a o strategie de tip di-
vide et impera: A ind primul nod care apare n parcurgerea n pre-
ordine, rezult a c a el este r ad acina arborelui. Ceea ce se a a la st anga
lui A n sirul dat n parcurgerea n inordine este subarborele st ang al
r ad acinii (la noi: parcurgerea n inordine a subarborelui st ang al lui
A este C, B, E, D, iar la parcurgerea n preordine aceleasi 4 simboluri
apar n ordinea B, C, D, E; analog, pentru partea dreapt a inordine:
G, F, preordine: F, G). La ecare pas se detecteaz a la fel ca mai sus
r ad acina ec arui subarbore, dup a care descendent ii s ai st ang si drept.
C and se ajunge la o secvent a format a dintrun singur nod, nu mai avem
ce s a determin am: arborele este complet construit.
A
C D
B F
G
E
Figura 12.1: Arborele care corespunde celor dou a secvent e: preordine
A, B, C, D, E, F, G si inordine C, B, E, D, A, G, F
Explicat ii: 4 puncte
Pasii efectuat i p an a la sf arsit: 3p
Reprezentare arbore: 1p
125
Este posibil ca s a se determine prin alt a metod a un arbore care respect a
doar una din secvent ele date. De exemplu, arborele din gura 12.2
produce doar parcurgerea n preordine conform secvent ei date, dar nu
si inordinea. (4p).
A
C
B F
E D
G
Figura 12.2: Arbore care produce la parcurgere n preordine
A, B, C, D, E, F, G, dar nu d a rezultat corect pentru inordine:
C, B, E, D, A, G, F, pe c and la noi se obt ine: D, C, E, B, A, F, G.
126
Anexa A
Metode utile n calculul
complexitat ii
A.1 Sume des ntalnite
1. Progresia aritmetic a:
a
k
= a
k1
+r, k = 2, a
1
si r dat i (A.1)
S =
n
k=1
a
k
=
(a
1
+a
n
)n
2
(A.2)
2. Sume particulare:
n
k=1
k =
n(n + 1)
2
= (n
2
) (A.3)
n
k=1
k
2
=
n(n + 1)(2n + 1)
6
= (n
3
) (A.4)
n
k=1
k
3
=
_
n(n + 1)
2
_
2
= (n
4
) (A.5)
si n general:
n
k=1
k
p
= (n
p+1
) (A.6)
3. Progresii geometrice:
127
a
k
= a
k1
r, k = 1, a
1
, r ,= 1 dat i
S =
n
k=1
a
k
=
n
k=1
a
1
r
k
= a
1
r
n1
k=0
r
k
= a
1
r
r
n
1
r 1
(A.7)
Dac a r < 1, atunci
S =
n
k=1
a
k
k=1
a
k
= a
1
1
1 r
(A.8)
A.2 Delimitarea sumelor
De multe ori, sumele nu se reg asesc n formele simple date mai sus. Exist a
diferite tehnici de determinare a unei major ari si minor ari a acestora. Pre-
zent am c ateva din ele mai jos.
A.2.1 Induct ia matematica
Una din modalit at ile usor de abordat pentru delimitarea unei sume este
bazat a pe induct ia matematic a. De exemplu, s a demonstr am c a seria arit-
metic a
n
k=1
k are valoarea
1
2
n(n+1). Putem verica usor pentru n = 1, n = 2
asa c a facem ipoteza de induct ie c a formula este adev arat a pentru orice n si
demonstr am c a are loc pentru n + 1. Avem
n+1
k=1
k =
n
k=1
k + (n + 1) =
1
2
n(n + 1) + (n + 1) =
1
2
(n + 1)(n + 2). (A.9)
Nu ntotdeauna putem determina valoarea exact a a unei sume. Pe noi
oricum ne intereseaz a ordinul sumei (deci constantele multiplicative si ter-
menii mici nu sunt ntotdeauna esent iali
1
). De exemplu, s a demonstr am c a
n
k=0
2
k
c2
n
pentru o anumit a constant a c, de la un rang nncolo (saun alt a
notat ie:
n
k=0
2
k
=O(2
n
)). Pentru condit ia init ial a n = 0 avem
0
k=0
2
k
= 1 c1,
c at timp c 1. Presupun and proprietatea de m arginire are loc pentru n s a
demonstr am c a are loc si pentru n + 1. Avem:
n+1
k=0
2
k
=
n
k=0
2
k
+ 2
n+1
c 2
n
+ 2
n+1
=
_
1
2
+
1
c
_
c 2
n+1
c 2
n+1
(A.10)
1
Dar: (2
3n
) = (2
n
); n acest caz constanta 3 nu poate neglijat a
128
c at timp (1/2 + 1/c) 1 sau, echivalent, c 2. Astfel,
n
k=0
2
k
= O(2
n
), ceea
ce am dorit s a ar at am.
Atent ion am cititorul asupra unui viciu de procedur a n cazul utiliz arii
acestui instrument matematic, care se reg aseste n urm atoarea demonstrat ie
corect a: ar at am c a
n
k=1
k = O(n). Desigur,
1
k=1
k = O(1). Accept and
delimitarea pentru n, o demonstr am acum pentru n + 1:
n+1
k=1
k =
n
k=1
k + (n + 1)
= O(n) + (n + 1) gresit !
= O(n + 1).
Greseala n argumentat ie este aceea c a O ascunde o constant a care
creste n funct ie de n si deci nu este constant a. Ar trebui s a ar at am c a exist a
o constant a care se ascunde n notat ia O() si care este deci valabil a pentru
tot i n.
A.2.2 Aproximarea prin integrale
C and o sum a poate exprimat a ca
n
k=m
f(k), unde f(k) este o funct ie
monoton cresc atoare, o putem m argini prin integrale:
_
n
m1
f(x)dx
n
k=m
f(k)
_
n+1
m
f(x)dx. (A.11)
Justicarea (geometric a, intuitiv a) pentru aceast a aproximare este ar atat a
n gura A.1. Suma este reprezentat a prin aria dreptunghiului din gur a,
iar integrala este regiunea hasurat a de sub curb a. C and f(k) este o funct ie
monoton descresc atoare, putem utiliza o metod a similar a pentru a obt ine
marginile
_
n+1
m
f(x)dx
n
k=m
f(k)
_
n
m1
f(x)dx. (A.12)
Aproximat ia integral a (A.12) d a o estimare str ans a pentru al n - lea
num ar armonic. Pentru o limit a inferioar a, obt inem
n
k=1
1
k
_
n+1
1
dx
x
= ln(n + 1). (A.13)
129
(a) M arginire inferioar a (b) M arginire superioar a
Figura A.1: M arginire prin integrale.
Pentru limita superioar a, deducem inegalitatea
n
k=2
1
k
_
n
1
dx
x
= ln n, (A.14)
care d a limita
n
k=1
1
k
ln n + 1. (A.15)
Avantajul acestei tehnici este c a permite at at determinarea unei m arginiri
inferioare, c at si a unei m arginiri superioare, care pot duce la o exprimare a
complexit at ii cu notat ia (mai exact a dec at O sau ).
Propunem cititorului s a aplice aceast a tehnic a pentru sumele prezentate
anterior
A.3 Analiza algoritmilor recursivi
Analiza unui algoritm recursiv implic a rezolvarea unui sistem de recurent e.
Vom vedea n continuare cum pot rezolvate astfel de recurent e.
Incepem
cu tehnica cea mai banal a.
A.3.1 Metoda iterat iei
Tehnica urm atoare cere ceva mai mult a tehnic a matematic a, dar rezul-
tatele sunt destul de expresive. Traiectoria ar : se execut a c at iva pasi, se
intuieste forma general a, iar apoi se demonstreaz a prin induct ie matema-
tic a c a aceast a form a este corect a. S a consider am, de exemplu, recurent a
130
problemei turnurilor din Hanoi. Pentru un n > 1 obt inem succesiv
t(n) = 2t(n1) +(1) = 2
2
t(n2) +(2) +(1) = . . . = 2
n1
t(1) +
n2
i=0
2
i
.
(A.16)
Rezult a t(n) = 2
n
1. Prin induct ie matematic a se demonstreaz a acum
cu usurint a c a aceast a formul a este corect a.
A.3.2 Recurent e liniare omogene
Vom prezenta modul de rezolvare al unor ecuat ii recurente liniare omo-
gene, adic a de forma:
a
0
t
n
+a
1
t
n1
+. . . +a
k
t
nk
= 0 (A.17)
unde t
i
sunt valorile pe care le c aut am, iar coecient ii a
i
sunt constante.
Vom atasa recurent ei (A.17) ecuat ia:
a
0
x
n
+a
1
x
n1
+. . . +a
k
x
nk
= 0 (A.18)
Solut iile acestei ecuat ii sunt e solut ia trivial a x = 0, care nu ne intereseaz a,
e solut iile ecuat iei de grad k
a
0
x
k
+a
1
x
k1
+. . . +a
k
= 0 (A.19)
care este ecuat ia caracteristic a a recurent ei (A.17).
Presupun and deocamdat a c a cele k r ad acini r
1
, r
2
, . . . , r
k
ale acestei ecuat ii
caracteristice sunt distincte, orice combinat ie liniar a
t
n
=
k
i=1
c
i
r
n
i
(A.20)
este o solut ie a recurent ei (A.17), unde constantele c
1
, c
2
, . . . , c
k
sunt deter-
minate de condit iile init iale.
S a exemplic am prin recurent a care deneste sirul lui Fibonacci:
t
n
= t
n1
+t
n2
, n 2 (A.21)
iar t
0
= 0, t
1
= 1. Putem s a rescriem aceast a recurent a sub forma
t
n
t
n1
t
n2
= 0 (A.22)
care are ecuat ia caracteristic a
x
2
x 1 = 0 (A.23)
131
cu r ad acinile r
1,2
= (1
5.
Deci, t
n
= 1/
5(r
n
1
r
n
2
). Observ am c a r
1
= = (1 +
5)/2, r
2
=
1
si
obt inem
t
n
= 1/
5(
n
()
n
)
Ca atare, implementarea recursiv a pentru determinarea celui de-al nlea ter-
men al sirului lui Fibonacci duce la o complexitate exponent ial a
2
.
Dac a r ad acinile ecuat iei caracteristice nu sunt distincte, se procedeaz a
dup a cum urmeaz a: dac a r este o r ad acin a de multiplicitate m a ecuat iei
caracteristice, atunci t
n
= r
n
, t
n
= nr
n
, t
n
= n
2
r
n
, . . . , t
n
= n
m1
r
n
sunt
solut ii pentru (A.17). Solut ia general a pentru o astfel de recurent a este
atunci o combinat ie liniar a a acestor termeni si a termenilor provenit i de la
celelalte r ad acini ale ecuat iei caracteristice. Ca mai sus, trebuie determinat
exact k constante din condit iile init iale.
Vom da din nou un exemplu. Fie recurent a
t
n
= 5t
n1
8t
n2
+ 4t
n3
, n 3 (A.25)
iar t
0
= 0, t
1
= 1, t
2
= 2. Ecuat ia caracteristic a are r ad acinile 1 (de multipli-
citate 1) si 2 (de multiplicitate 2). Solut ia general a este:
t
n
= c
1
1
n
+c
2
2
n
+c
3
n2
n
.
Din condit iile init iale, obt inem c
1
= 2, c
2
= 2, c
3
= 1/2.
A.3.3 Recurent e liniare neomogene
Consider am acum recurent e de urm atoarea form a mai general a
a
0
t
n
+a
1
t
n1
+. . . +a
k
t
nk
= b
n
p(n) (A.26)
unde b este o constant a, iar p(n) este un polinom n n de grad d
2
Pentru o complexitatea logaritmic a, a se vedea capitolul 5.
132
Pentru a rezolva (A.26), este sucient s a lu am urm atoarea ecuat ie carac-
teristic a:
(a
0
x
k
+a
1
x
k1
+. . . +a
k
)(x b)
d+1
= 0. (A.27)
Odat a ce s-a obt inut aceast a ecuat ie, se procedeaz a ca n cazul omogen.
Vom rezolva acum recurent a corespunz atoare problemei turnurilor din
Hanoi:
t
n
= 2t
n1
+ 1, n 1
iar t
0
= 0. rescriem recurent a astfel
t
n
2t
n1
= 1
care este de forma (A.26 ) cu b = 1 si p(n) = 1, un polinom de gradul 0.
Ecuat ia caracteristic a este atunci (x2)(x1) = 0, cu solut iile 1, 2. Solut ia
general a a recurent ei este
t
n
= c
1
1
n
+c
2
2
n
.
Avem nevoie de dou a condit ii init iale. Stim c a t
0
= 0; pentru a g asi cea de-a
doua condit ie calcul am
t
1
= 2t
0
+ 1.
Din condit iile init iale, obt inem
t
n
= 2
n
1.
din care se deduce c a t
n
= (2
n
).
133
134
Anexa B
Rezolvari
B.1 Rezolvari pentru capitolul 3
1. Problema 1.
(a) Exemplul 1. acest program cont ine doar instruct iuni elementare
care cer un timp constant de execut ie. Ca atare, timpul total este
m arginit superior de o constant a, fapt gurat prin notat ia (1).
(b) Exemplul 2: justicarea este aceeasi cu cea de la punctul prece-
dent, deci complexitatea este (1).
(c) Exemplul 3: citirea datelor de intrare are un cost de t
1
(n) = c
1
(n+1), unde c
1
este o constant a reprezent and timpul necesar citirii
unei valori. Atribuirea s = 0 se execut a ntr-un timp constant
t
2
= c
2
, independent de dimensiunea datelor de intrare. Ciclarea
nseamn a t
3
= c
3
n, unde c
3
este timpul necesar pentru calculul
sumei si efectuarea atribuirii; de asemenea, c
3
nu depinde de n.
Asarea se face n timpul t
4
= c
4
(constant).
Ca atare,
T(n) = t
1
(n) +t
2
(n) +t
3
(n) +t
4
(n) = c
1
(n +1) +c
2
+c
3
n +c
4
Conform propriet at ii 5, pagina 24, avem c a:
T(n) = (c
1
(n + 1) +c
2
+c
3
n +c
4
)
= (max(c
1
(n + 1) +c
3
n), c
2
+c
4
)
= (c
1
(n + 1) +c
2
n) = ((c
1
+c
3
)n +c
1
)
= ((c
1
+c
2
)n) = (n),
ultima egalitate av and loc datorit a propriet at ii 7, pagina 24.
135
(d) Exemplul 4: citirea datelor este t
1
(n) = c
1
(n + 1); atribuirile
nseamn a t
2
(n) = 3 c
2
, unde c
2
este timpul necesar unei atribu-
iri. Ciclul cu num arator nseamn a t
2
(n) = c
3
n, timpul c
3
ind
constant din cauz a c a se fac evalu ari de expresii logice si atribuiri,
costul ec arei operat ii n parte ind independent de n.
Deci
T(n) = t
1
(n)+t
2
(n)+t
3
(n) = (c
1
(n + 1) + 3 c
2
+c
3
n) = (n)
O alt a justicare: sirul este parcurs o singur a dat a, pentru e-
care element al s au efectu anduse operat ii cu cost (1); n total
complexitatea este (n).
(e) Exemplul 5: analiza algoritmului lui Euclid este destul de dicil a.
Complexitatea algoritmului este (log (min(a, b))). A se vedea de
exemplu [2].
(f) Exemplul 6: corpul ciclului cel mai interior se execut a n timp
constant deoarece cont ine doar instruct iuni elementare (atribuire,
asare). Se execut a de un num ar constant de ori, deci ciclul repet a
. . . p an a c and k = 5 se execut a ntr-un timp constant. La fel este
si cu ciclul repet a . . . p an a c and j = 4: corpul s au se excut a n
timp constant, de un num ar constant de ori. Idem n cazul ciclu-
lui cu contor exterior pentru. Ca atare, timpul total de execut ie
este m arginit superior de o constant a, complexitatea ind (1).
Propunem cititorului scrierea unui algoritm pentru listarea com-
bin arilor c ate 3 din mult imea 1, 2, . . . , n. Care este n acest caz
complexitatea?
2. Problema 2:
Start ProdusScalar
citeste( n, (a(i), i = 1, n), (b(i), i = 1, n) )
ps = 00 este element neutru pentru adunare
pentru i = 1, n
dac a pasul este 1, se poate omite
ps = ps +a(i) b(i)
sf arsit pentru
scrie( Produsul scalar este: , ps )
Stop
Complexitatea este (n).
3. Problema 3.
Ideea este de a parcurge sirul si a compara ecare element cu x; dac a
136
acest element este g asit, atunci este oprit a c autarea, altfel se merge la
urm atorul element. La sf arsit se raporteaz a rezultatul.
Pentru a semnala faptul c a x a fost g asit, vom folosi o variabil a boolean a
gasit care va primi valoarea adevarat dac a x a fost g asit n sir, fals n
caz contrar.
Start C autareLiniar a
citeste( n, (a(i), i = 1, n), x )
gasit = falsdeocamdat a nu am g asit pe x n a
i = 1i este indicele elementului curent din sir
repet a
dac a a(i) = x atunci
gasit = adevarat
pozitie = ipozitie este pozitia elementului x n sir
altfel
i = i + 1
sf arsit dac a
p an a c and i > n sau (gasit = adevarat)
dac a gasit = adevarat atunci
scrie( Am g asit , x, pe pozit ia , pozitie )
altfel
scrie( x, nu a fost g asit )
sf arsit dac a
Stop
Complexitatea este (n), cazul cel mai defavorabil ind c and x nu se
a a n sir.
Observat ie: Deoarece execut ia instruct iunilor din interiorul ciclului tre-
buie s a se fac a cel put in o dat a, este corect a utilizarea unui ciclu repet a.
4. Problema 4: vom folosi un algoritm asem an ator cu cel de la problema
precedent a, folosind informat ia c a sirul este ordonat cresc ator. Vom da
dou a variante, cu analiz a de complexitate.
(a) Prima variant a: ncepem c autarea, dar vom impune o condit ie
suplimentar a: trebuie ca permanent x a(i). Dac a avem x >
a(i), atunci este clar c a x nu mai poate g asit la dreapta indicelui
i.
Start C autareLiniar aCresc ator
citeste( n, (a(i), i = 1, n), x )
gasit = falsdeocamdat a nu am g asit pe x n a
i = 1i este indicele elementului curent din sir
137
repet a
dac a a(i) = x atunci
gasit = adevarat
pozitie = ipozitie este pozitia elementului x n sir
altfel
i = i + 1
sf arsit dac a
p an a c and i > n sau gasit = adevarat sau x > a(i)
dac a gasit = adevarat atunci
scrie( Am g asit , x, pe pozit ia , pozitie )
altfel
scrie( x, nu a fost g asit )
sf arsit dac a
Stop
Complexitatea este aceeasi ca la algoritmul precedent: (n).
Observat ie Este esent ial ca testarea i > n s a se fac a nainte de
testarea a(i) x; dac a spre exemplu locul lor ar fost inversat,
atunci era posibil ca s a avem i = n + 1, iar condit ia a(i) x s a
e testat a, desi a(n + 1) nu exist a.
(b) A doua variant a speculeaz a mai inteligent faptul c a sirul este gata
sortat. Putem mp art i sirul n dou a subsiruri de dimensiuni c at
mai apropiate. Se testeaz a dac a elementul de la mijloc este egal
cu x. Dac a da, atunci c autarea se opreste cu succes. Dac a nu, si
x <elementul din mijloc, atunci c autarea va continua s a se fac a n
prima jum atate a sirului (e clar c a n a doua jum atate nu poate
g asit); dac a x este mai mare dec at elementul de la jumatate,
atunci c autarea se va continua n a doua jum atate. C autarea
continu a p an a c and e se g aseste x n sir, e nu mai avem nici un
element de cercetat, caz care nseamn a c autare f ar a succes.
Acest algoritm se numeste algoritmul c aut arii binare (prin nju-
m at at ire).
Start C autareBinar a
citeste( n, (a(i), i = 1, n), x )
gasit = falsvariabila gasit are aceeasi semnicat ie ca n
algoritmul anterior
stanga = 1
dreapta = n
stanga si dreapta reprezint a capetelentre care se face c autarea
lui x
Initial, c autarea se face n tot vectorul
138
c at timp gasit = fals si stanga dreapta
nu l-am g asit pe x si mai avem unde c auta
mijloc =
_
stanga+dreapta
2
k=1
(a k +b) = (n
2
)
Exemplu: pentru n = 4, a = (10, 20, 30, 40) vom avea:
142
diferit = (10, 20, 30, 40)
contor = (1, 1, 1, 1)
k = 4
cel mai frecvent: 10
frecvent a: 1
8. Problema 8: vom prota de faptul c a vectorul dat este sortat cresc ator.
Vom c auta o secvent a de numere constante, de lungime maxim a.
Start CelMaiDes
inceputSecventa = 1
sfarsitSecventa = 1
lungimeSecventaMaxima = 0
suntInSir = adevarat
c at timp suntInSir = adevarat
c at timp sfarsitSecventa n si a(inceputSecventa) = a(sfarsitSecventa)
sfarsitSecventa = sfarsitSecventa + 1
sf arsit c at timp
dac a sfarsitSecventainceputSecventa > lungimeSecventaMaxima
atunci
apareMaxim = a(inceputSecventa)
lungimeSecventaMaxima = sfarsitSecventainceputSecventa
sf arsit dac a
inceputSecventa = sfarsitSecventa
dac a inceputSecventa > n atunci
suntInSir = falsam parcusr tot sirul
sf arsit dac a
sf arsit c at timp
scrie( Num arul cel mai frecvent: , apareMaxim )
scrie( Apare de , lungimeSecventaMaxima, ori )
Stop
Complexitate: se observ a c a valoarea sfarsitSecventa ia pe r and va-
lorile 1, 2, . . . , n+1; de ecare dat a sunt efectuate operat ii elementare,
deci avem T(n) = (n + 1) = (n).
Observat ie: Pentru a rezolva problema de la punctul anterior, am pu-
tea face o sortare a sirului, dup a care s a aplic am algoritmul de mai
sus. Complexitatea total a ar : sortarea implic a un timp (nlog n),
algoritmul anterior (n), deci per total (nlog n), sensibil mai bine
dec at (n
2
) care fusese obt inut anterior.
9. Problema 9:
143
Start Matrice
citeste( n )
citeste( ((a(i, j), j = 1, n), i = 1, n) )
subpunctul a
p = 11 este element neutru pentru nmult ire
pentru i = 1, n
pentru j = 1, n
dac a a(i, j) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Produsul elementelor nenule din matrice este: , p )
subpunctul b
p = 1
pentru i = 1, n
dac a a(i, i) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
scrie( Produsul elementelor nenule de pe diagonala principal a este:
, p )
subpunctul c
p = 1
pentru i = 2, n
pentru j = 1, i 1
dac a a(i, j) ,= 0 atunci
p = p a(i, j)
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Prod. elem. de sub diagonala principal a este:, p )
Stop
Complexitate:
(a) (n
2
) (ecare element al matricii este luat n considerare o sin-
gur a dat a, efectu andu-se cu el operat ii elementare);
(b) (n);
(c) T(n) =
n
i=2
(i 1)c = c
n
i=2
(i 1) = c
n(n1)
2
, deci T(n) = (n
2
).
144
B.2 Rezolvari pentru capitolul 4
1. Problema 1: Vom folosi pentru memorarea elementelor din coad a un
vector v de n elemente. Vom presupune c a indicii vectorului sunt ntre
0 si n 1. Deoarece coada este circular a, dup a locat ia de indice n 1
urmeaz a locat ia de indice 0. Init ial, coada este vid a, fapt semnalat prin
inceput = sfarsit = 0.
x Coada
sfarsit = (sfarsit + 1)mod n
dac a sfarsit = inceput atunci
Coada este plin a
altfel
v(sfarsit) = x
sf arsit dac a
Return
x Coada
dac a inceput = sfarsit atunci
Coada este vid a
altfel
inceput = (inceput + 1)mod n
x = v(inceput)
sf arsit dac a
Return
Complexitatea ec arui subalgoritm este (1). Init ial avem inceput =
sfarsit = 0.
Observat ie: Se folosesc efectiv doar n 1 locat ii ale vectorului; dar n
acest mod se poate distinge ntre situat iile de coad a plin a si coad a vid a.
2. Problema 2:
(a) Parcurgerea n inordine, iterativ:
InordineIterativ(rad)
i = rad
S = S este o stiv a
repet a
c at timp LS(i) ,=
i S
i = LS(i)
sf arsit c at timp
scrie( INFO(i) )
145
c at timp LD(i) =
dac a S = atunci
Return se iese din subalgoritm, deci si din ciclul innit
sf arsit dac a
i S
scrie( INFO(i) )
sf arsit c at timp
i = LD(i)
p an a c and falsciclu innit, din care se iese datorit a lui Return
(b) Parcurgerea n postordine, iterativ:
PostordineIterativ( rad )
i = rad
S = S este o stiv a
repet a
c at timp LS(i) ,=
i S
i = LS(i)
sf arsit c at timp
c at timp LD(i) =
repet a
scrie( INFO(i) )
dac a S = atunci
Returnse iese din subalgoritm, deci si din ciclul in-
nit
sf arsit dac a
j = i
i S
p an a c and j = LS(i)
sf arsit c at timp
i S
i = LD(i)
p an a c and falsciclu innit, din care se iese datorit a lui Return
Apelul subalgoritmilor de mai sus se face av and drept parametru de
apel rad, reprezent and adresa r ad acinii arborelui.
Complexitatea ec areia din proceduri este de (n), unde n este num arul
de v arfuri ale arborelui.
3. Problema 3:
Vom extrage succesiv v arful stivei S si l vom depune ntr-o alt a stiv a
146
T. Extragerile nceteaz a e c and S devine vid a, e c and x este g asit.
Elementele din T vor depuse napoi n S.
Extrage( S, x )
T =
gasitx = fals
c at timp S ,= si gasitx = fals
a S scoatem v arful stivei
dac a a ,= x atunci
a T l depunem n T
altfel
gasitx = adevarat
sf arsit dac a
sf arsit c at timp
c at timp T ,=
a T
a S
sf arsit c at timp
Return
Complexitate: cazul cel mai defavorabil este acela n care x nu se
g aseste n S.
In acest caz, tot cont inutul lui S este trecut n T si
apoi repus n S. Complexitatea este deci ([S[), unde [S[ reprezint a
num arul de elemente aate init ial n S.
Observat ie: Primul ciclu c at timp poate scris mai adecvat ca un ciclu
repet a, av andn vedere faptul c a execut ia ciclui se face cel put in o dat a.
4. Problema 4:
Rezolvarea este asem anatoare cu cea de la punctul precedent.
Insereaza( S, x, y )
T =
gasitx=fals
c at timp S ,= si gasitx = fals
a S scoatem v arful stivei
dac a a ,= x atunci
a T l depunem n T
altfel
gasitx = adevarat
a S
sf arsit dac a
sf arsit c at timp
dac a gasitx = adevarat atunci
147
y S
sf arsit dac a
c at timp T ,=
a T
a S
sf arsit c at timp
Return
Complexitatea este ([S[ + 1) = ([S[), motivat ia ind asem an atoare
cu cea de la punctul precedent.
5. Problema 5:
Vom folosi dou a stive: Stiva1, Stiva2.
x Coada
dac a Stiva1 = atunci
Goleste(Stiva2, Stiva1)Goleste elementele din Stiva2 n Stiva1
sf arsit dac a
x Stiva1
Return
x Coada
dac a Stiva2 = atunci
Goleste(Stiva1, Stiva2)Goleste elementele din Stiva1 n Stiva2
sf arsit dac a
dac a Stiva2 = atunci
Coada este vida
altfel
x Stiva2
sf arsit dac a
Return
Subalgoritmul Goleste(A, B) unde A si B sunt stive va trece toate ele-
mentele din An B, prin extrageri repetate.
Goleste(A, B)
c at timp A ,=
x A
x B
sf arsit c at timp
Return
Num arul de operat ii de inserare si extragere n ecare caz zunt:
(a) Subalgoritmul Goleste(A, B) efectueaz a 2[A[ extrageri ([A[ este
148
num arul de elemente din stiva A);
(b) Subalgoritmul x Coada efectueaz a 2[Stiva2[+1 = 2[Coada[+1
operat ii de inserare/extragere;
(c) Subalgoritmul x Coada efectueaz a 2[Stiva1[+1 = 2[Coada[+1
operat ii de inserare/extragere;
6. Problema 6:
Vom folosi dou a cozi: Coada1, Coada2.
x Stiva
x Coada1
Return
x Stiva
dac a Coada1 = atunci
eroare: stiva vid a
altfel
c at timp Coada1 ,=
x Coada1
dac a Coada1 ,= atunci
x nu este ultimul element din Coada1
x Coada2
sf arsit dac a
sf arsit c at timpGoleste Coada2 n Coada1
c at timp Coada2 ,=
y Coada2
y Coada1
sf arsit c at timp
sf arsit dac a
Return
Num arul de operat ii de inserare/extragere pentru ecare din cei doi
subalgoritmi sunt:
(a) Subalgoritmul x Stiva efectueaz a o inserare
(b) Subalgoritmul x Stiva are num arul de operat ii cerut egal cu
2([Coada1[ 1) + 1 (primul ciclu) adunat cu 2([Coada1[ 1), n
total 4[Coada1[ 3 = 4[Stiva[ 3.
Suger am cititorului s a g aseasc a si alte soluct ii pentru aceast a pro-
blem a.
149
B.3 Rezolvari pentru capitolul 5
1. Problema 1. Denim maximul unui sir x = (x(1), x(2), . . . , x(n)) sub
form a recursiv a astfel:
maxim(x(1 . . . n)) =
_
x(1), dac a n=1
maxx(n), x(1 . . . n 1), dac a n > 1
unde maxa, b este maximul dintre a si b. Algoritmul este dat mai
jos:
Start MaximRec
citeste( n, (x(i), i = 1, n) )
M = Maxim(x, n)
scrie( M )
Stop
unde subalgoritmul recursiv Maxim este:
Maxim(x, n)
dac a n = 1 atunci
MaximRec = x(1)
altfel
MaximRec = maxx(n), Maxim(x, n 1)
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n1)+c care are solut ia
T(n) = (n).
2. Problema 2. Denim suma elementelor unu sir x = (x(1), . . . , x(n))
sub form a recursiv a astfel:
suma(x(1 . . . n)) =
_
0, dac a n=0
x(n) +suma(x(1 . . . n 1)), dac a n > 0
Start SumaRec
citeste( n, (x(i), i = 1, n) )
S = Suma(x, n)
scrie( S )
Stop
unde subalgoritmul recursiv Suma este:
Suma(x, n)
dac a n = 0 atunci
150
Suma = 0
altfel
Suma = x(n) +Suma(x, n 1)
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n1)+c care are solut ia
T(n) = (n).
3. Problema 3. Vom da o formul a recursiv a de calcul a puterii naturale a
unui num ar.
a
n
=
_
_
1, dac a n = 0
a, dac a n = 1
_
a
n/2
_
2
, dac a n > 1, n par
a
_
a
n/2
_
2
, dac a n > 1, n impar
Subalgoritmul recursiv este:
Putere(a, n)
dac a n = 0 atunci
Putere = 1
Return
sf arsit dac a
dac a n = 1 atunci
Putere = a
Return
sf arsit dac a
temp = Putere(a, n/2|)
dac a n mod 2 = 0 atunci
n este par
Putere = temp
altfel
Putere = a temp
sf arsit dac a
Return
Complexitatea este dat a de ecuat ia T(n) = T(n/2)+c, de unde T(n) =
(log n) (rezultat al teoremei 1, pagina 72).
4. Problema 4. Pentru a
15
, conform algoritmului precedent, avem:
a
15
=
_
_
(a)
2
a
_
2
a
_
2
a
151
deci n total 6 nmult iri.
Dar a
15
se poate calcula astfel: se calculeaz a termenii a
2
, a
3
= a
2
a, a
6
=
a
3
a
3
, a
12
= a
6
a
6
, a
15
= a
12
a
3
, deci cu 5 nmult iri.
5. Problema 5. S a consider am matricea:
A =
_
0 1
1 1
_
Calcul and produsul:
A
_
f
n1
f
n
_
obt inem matricea
_
f
n
f
n+1
_
de unde deducem
_
f
n1
f
n
_
= A
n1
_
f
0
f
1
_
Modic and algoritmul de la problema 3 s a ridice la putere o matrice n
loc de un scalar, obt inem termenul f
n
n timp (log n).
6. Problema 6. Algoritmuii recusrivi pentru parcurgeri sunt urm atorii:
(a) Parcurgerean preordine se efectueaz a astfel: se prelucreaz a informa-
t ia r ad acinii, apoi se prelucreaz a recursiv subarborele st ang, apoi
subarborele drept.
Preordine(Rad)
dac a Rad ,= atunci
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
Preordine(LS(Rad))
Preordine(LD(Rad))
sf arsit dac a
Return
Apelul acestui subalgoritm se face cu Preordine(Rad), unde Rad
reprezint a r ad acina subarborelui.
(b) Parcurgerea recursiv a n postordine se efectueaz a astfel: se par-
curge recursiv subarborele st ang, apoi subarborele drept, apoi se
prelucreaz a informat ia din r ad acin a.
152
Postordine(Rad)
dac a Rad ,= atunci
Postordine(LS(Rad))
Postordine(LD(Rad))
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
sf arsit dac a
Return
Apelul se face ce n cazul anterior.
(c) Parcurgerea recursiv a n inordine se efectueaz a astfel: se par-
curge recursiv subarborele st ang, apoi se prelucreaz a informat ia
din r ad acin a, apoi se parcurge recursiv subarborele drept.
Inordine(Rad)
dac a Rad ,= atunci
Inordine(LS(Rad))
scrie( Info(Rad) )Sau orice alt subalgoritm de prelucrarea
a informat iei din Rad
Inordine(LD(Rad))
sf arsit dac a
Return
Apelul se face ce n cazul anterior.
B.4 Rezolvari pentru capitolul 6
1. Problema 1.
Vom da dou a variante de rezolvare: iterativ a si recursiv a. Ambele
variante vor folosi doi vectori de s arituri: sarituraI si sarituraJ cu
c ate 8 elemente, reprezent and cele 8 deplas ari de la pozit ia curent a: de
exemplu, dac a pozit ia curent a este pe linia i si coloana j, atunci prima
s aritur a va duce calul la coordonatele (i+sarituraI(1), j+sarituraJ(1)
(cu condit ia s a nu se ias a din perimetrul tablei).
(a) Varianta iterativ a: pentru refacerea pasului napoi vom folosi
o matrice p atratic a deLa de ordinul n, care va ret ine pentru ecare
celul a de coordonate (i, j) indicele s ariturii care a determinat atingerea
pozit iei respective (vom putea sti astfel de unde sa s arit n pozit ia
curent a). Solut ia se d a sub forma unei matrice p atratice de ordinul n
cont in and n ecare celul a de coordonate (i, j) indicele s ariturii ce se
face n continuare (cu except ia ultimei celule n care se sare).
153
Start CalSah
citeste( n )
sarituraI(1) = +1, sarituraJ(1) = +2
sarituraI(2) = 1, sarituraJ(2) = +2
sarituraI(3) = +1, sarituraJ(3) = 2
sarituraI(4) = 1, sarituraJ(4) = 2
sarituraI(5) = +2, sarituraJ(5) = +1
sarituraI(6) = 2, sarituraJ(6) = +1
sarituraI(7) = +2, sarituraJ(7) = 1
sarituraI(8) = 2, sarituraJ(8) = 1
pentru i = 1, n
pentru j = 1, n
deLa(i, j) = 0
tabla(i, j) = 0
sf arsit pentru
sf arsit pentru
nrSaritura = 1
i = j = 1
c at timp nrSaritura > 0
dac a nrSaritura = n
2
atunci
ScrieSolutie(tabla, n)
indiceSarituraInapoi = deLa(i, j)
tabla(i, j) = 0
i = i sarituraI(indiceSarituraInapoi)
j = j sarituraJ(indiceSarituraInapoi)
nrSaritura = nrSaritura 1
sf arsit dac a
dac a tabla(i, j) < 8 atunci
tabla(i, j) = tabla(i, j) + 1
iInainte = i +sarituraI(tabla(i, j))
jInainte = j +sarituraJ(tabla(i, j))
dac a PoateSari(iInainte, jInainte, tabla, n)=adevarat atunci
deLa(iInainte, jInainte) = tabla(i, j)
i = iInainte
j = jInainte
nrSaritura = nrSaritura + 1
sf arsit dac a
altfel
dac a nrSaritura > 1 atunci
iInapoi = i sarituraI(deLa(i, j))
jInapoi = j sarituraJ(deLa(i, j))
154
tabla(i, j) = 0
i = iInapoi
j = jInapoi
sf arsit dac a
nrSaritura = nrSaritura 1
sf arsit dac a
sf arsit c at timp
Stop
ScrieSolutie(tabla, n)
pentru i = 1, n
pentru j = 1, n
scrie( tabla(i, j) )
sf arsit pentru
sf arsit pentru
Return
PoateSari(linie, coloana, tabla, n)
dac a linie > 0 si linie < n + 1 si coloana > 0 si coloana < n + 1 si
tabla(linie, coloana) = 0 atunci
rezultat = adevarat
altfel
rezultat = fals
sf arsit dac a
PoateSari = rezultat
Return
(b) Varianta recursiv a
Cal(i, j, n, nrSaritura, tabla)
dac a nrSaritura = n n atunci
ScrieSolutie(tabla, n)
altfel
pentru indiceSaritura = 1, 8
iInainte = i +sarituraI[indiceSaritura]
jInainte = j +sarituraJ[indiceSaritura]
dac a PoateSari(iUrmator, jUrmator, tabla, n)=adev atunci
tabla[iInainte, jInainte] = nrSaritura + 1
Cal(iInainte, jInainte, n, nrSaritura + 1, tabla)
tabla[iInainte, jInainte] = 0
sf arsit dac a
sf arsit pentru
sf arsit dac a
Return
155
Subalgoritmii ScrieSolutie si PoateSari sunt identici cu cei de la varianta
iterativ a.
Start CalSah
citeste( n )
sarituraI(1) = +1, sarituraJ(2) = +2
sarituraI(2) = 1, sarituraJ(2) = +2
sarituraI(3) = +1, sarituraJ(3) = 2
sarituraI(4) = 1, sarituraJ(4) = 2
sarituraI(5) = +2, sarituraJ(5) = +1
sarituraI(6) = 2, sarituraJ(2) = +1
sarituraI(7) = +2, sarituraJ(2) = 1
sarituraI(1) = 2, sarituraJ(2) = 1
pentru i = 1, n
pentru j = 1, n
tabla(i, j) = 0
sf arsit pentru
sf arsit pentru
tabla(1, 1) = 1
Cal(1, 1, n, 1, tabla)
Stop
2. Problema 2.
Sa demonstrat cu ajutorul calculatorului c a 4 culori sunt suciente
pentru a colora cu restrict iile date orice hart a. Vom da dou a variante,
iterativ a si recursiv a.
In ambele variante vectorul culoare de n elemente
va cont ine culorile t arilor.
(a) Varianta iterativ a.
Start ColorareHarti
citeste( n )
citeste( ((a(i, j), j = 1, n), i = 1, n) )
pentru i = 1, n
culoare(i) = 0
sf arsit pentru
numarTara = 1
c at timp numarTara > 0
dac a numarTara = n + 1 atunci
scrie( (culoare(i), i = 1, n) )
numarTara = numarTara 1
sf arsit dac a
dac a culoare(numarTara) < 4 atunci
156
culoare(numarTara) = culoare(numarTara) + 1
dac a BineColorat(a, numarTara, culoare) = adev atunci
numarTara = numarTara + 1
sf arsit dac a
altfel
culoare(numarTara) = 0
numarTara = numarTara 1
sf arsit dac a
sf arsit c at timp
Stop
Subalgoritmul BineColorat(vecin, numarTara, culoare) returneaz a adev arat
dac a culoarea t arii curente (numarTara)satisface restrict iile cerute fat a
de t arile anterior colorate.
BineColorat(a, numarTara, culoare)
corect = adevarat
i = 1
c at timp corect = adevarat si i < numarTara
dac a a(i, numarTara) = 1 si culoare(i) = culoare(numarTara)
atunci
corect = fals
altfel
i = i + 1
sf arsit dac a
sf arsit c at timp
BineColorat = corect
Return
(b) Varianta recursiv a.
Coloreaza(a, n, culoare, numarTara)
dac a numarTara = n + 1 atunci
scrie( (culoare(i), i = 1, n) )
altfel
pentru k = 1, 4
culoare(numarTara) = k
dac a BineColorat(a, numarTara, culori)= adev atunci
Coloreaza(a, n, culoare, numarTara + 1)
sf arsit dac a
sf arsit pentru
sf arsit dac a
Return
157
Subalgoritmul BineColorat este identic cu cel de la varianta iterativ a.
Utilizarea subalgoritmului recursiv se face astfel:
Start ColorareHarti
citeste( n )
citeste( ((vecin(i, j), j = 1, n), i = 1, n) )
Coloreaza(vecin, n, culoare, 1)
Stop
3. Problema 3.
Vom nota b arbat ii cu b
1
, . . . , b
n
iar femeile cu f
1
, . . . , f
m
. Vom genera
delegat iile folosind doi vectori, unul pentru indicii de b arbat i, cel alalt
pentru indicii de femei (vectorii vb, respectiv vf). Fiecare vector are o
componennt a de indice 0 care va avea permanent valoarea 0.
In vectorul
vf vom avea generate p componente (k p m), iar n vectorul vb
vom avea q elemente (0 q n); varianta q = 0 exist a deoarece se
pot forma delegat ii n care s a nu existe nici un b arbat.
Varianta dat a mai jos este recursiv a. Pentru subalgoritmul Generare-
Delegatii, parametrii fc si bc reprezint a indicele de vector vf, respectiv
vb pentru care se efectueaz a alegerea unei femei, respectiv b arbat.
GenerareDelegatii(p, fc, m, q, bc, n, vf, vb)
dac a fc = p + 1 atunci
am generat tot i indiciii pentru femei
dac a bc = q + 1 atunci
am generat tot i indiciii pentru b arbat i
scrie( (vf(i), i = 1, p) )
scrie( (vb(i), i = 1, q) )
altfel
pentru i = vb(bc 1) + 1, n q +bc
vb(bc) = i
GenerareDelegatii(p, fc, m, q, bc + 1, n, vf, vb)
sf arsit pentru
sf arsit dac a
altfel
pentru i = vf(fc 1) + 1, mp +fc
vf(fc) = i
GenerareDelegatii(p, fc + 1, m, q, bc, n, vf, vb)
sf arsit pentru
sf arsit dac a
Return
Start Delegatii
158
citeste( m, n, k )
vf(0) = vb(0) = 0
pentru p = k, m
pentru q = 0, n
GenerareDelegatii(p, 1, m, q, 1, n, vf, vb)
sf arsit pentru
sf arsit pentru
Stop
Pentru o variant a iterativ a, a se citi capitolul 7, sectiunea 7.5 (generare
de combin ari).
4. Problema 4.
Vom da mai jos o variant a recursiv a. Consider am rest ca ind res-
tul care mai este de pl atit, solutie un vector cu n elemente, 0
solutie(i) b(i), bc tipul bancnotei curente.
Plata(rest, n, solutie, bc)
dac a rest = 0 atunci
scrie( (solutie(i), i = 1, bc 1) )
altfel
dac a rest > 0 si bc n atunci
pentru k = 0, b(bc)
solutie(bc) = k
Plata(rest k v(bc), solutie, bc + 1)
sf arsit pentru
sf arsit dac a
sf arsit dac a
Return
Start PlataSuma
citeste( n, S )
citeste( (b(i), i = 1, n) )
citeste( (v(i), i = 1, n) )
Plata(S, n, solutie, 1)
Stop
Observat ie Orice problem a cu datele ca mai sus poate transformat a
ntruna n care vectorul b cont ine doar valoarea 1, prin crearea unui
vector v
i=1
g(i), atunci n mod evident solut ia dat a
de vectorul f va avea forma f = (1, 1, . . . , 1) (se iau toate obiectele),
ceea ce evident nseamn a optim. Vom considera deci cazul n care
G <
i=1
f(i)c(i) (B.2)
si
G =
k
i=1
f(i)g(i) (B.3)
Fie S
= (f
(1), . . . , f
(n)) (B.4)
fract iunile din obiecte care se iau, pentru a realiza S
:
S
=
n
i=1
f
(i)c(i) (B.5)
Avem:
G
=
n
i=1
f
(i)g(i) (B.6)
unde G
.
Putem avea urm atoarele situat ii:
(a) Dac a (prin absurd) S
(p) ,= 1 (n ipoteza n
care un asemenea p exist a). Vom transforma f
(p) n f
(p) =
f
(t) f
(t) =
f
(t) 0, astfel nc at
g(t) = g(p) (B.7)
170
Pentru i ,= p, t vom avea f
(i) = f
(i). Atunci:
S
i
f
(i)c(i) =
i=p,t
f
(i)c(i) + (f
(p) +)c(p) +
(f
(t) )c(t) = S
= S
= S
si procedeul se continu a cu
urm atorul p. Dac a S
< S
.
Dac a nu (mai) exist a nici un p cu proprietatea f
(k). Dac a
f
(k)
la (si sc aderea unui f
= S
i=1
(n i +1)t
p
k
(B.10)
Fie p permutarea care determin a T din (B.10) minim. Fie p
permuta-
rea care se obt ine din p printro inversiune: p
(i) = p(j), p
(j) = p(i)
(i < j), p
), ceea ce
este echivalent cu (j i)(t
p
i
t
p
j
) 0, ceea ce conduce la t
p
i
< t
p
j
,
ceea ce conrm a valabilitatea strategiei.
Algoritmul este:
Start Procesare
citeste( n, (t(i), i = 1, n) )
pentru i = 1, n
p(i) = i
sf arsit pentru
Sortaret, p, n
pentru i = 1, n
scrie( p(i) )
sf arsit pentru
Stop
173
Algoritmul Sortare(t, p, n) sorteaz a elementele lui t, n paralel f ac and
aceleasi interschimb ari n vectorul de permutare p.
B.9 Rezolvari pentru capitolul 11
1. Problema 1. Tablourile m si s, analoage celor din Tabelul 11.2, pagina
116, au valorile:
1 2 3 4 5 6 1 2 3 4 5 6
0 150 330 405 1655 2010 0 1 2 2 4 2
0 0 360 330 2430 1950 0 0 2 2 2 2
0 0 0 180 930 1770 0 0 0 3 4 4
0 0 0 0 3000 1860 0 0 0 0 4 4
0 0 0 0 0 1500 0 0 0 0 0 5
0 0 0 0 0 0 0 0 0 0 0 0
De aici tragem concluzia c a num arul optim de nmult iri scalare este
m(1, 6) = 2010. Pentru determinarea modului n care se facenmult irea,
folosim informat ia din matricea s: s(1, 6) = 2, deci vom avea paranteza-
rea (A
1
A
2
) (A
3
. . . A
6
). Pentru a determina cum se face parantezarea
pentru produsul A
36
, folosim s(3, 6) = 4, de unde deducem c a grup am
A
3...6
= (A
3
A
4
) (A
5
A
6
).
In nal, obt inem parantezarea complet a:
((A
1
A
2
) ((A
3
A
4
) (A
5
A
6
)))
2. Problema 2. Demonstrat ia se face prin induct ie matematic a dup a
num arul n de matrici. Fie P(n) propozit ia parantezarea complet a
a unui sir cu n matrici are exact n 1 paranteze.
Vericarea:
(a) P(1): o matrice reprezint a o expresie complet parantezat a
(b) P(2): (A
1
A
2
) este singura expresie complet parantezat a asociat a
produsului a dou a matrici, deci avem o pereche de paranteze.
Demonstrat ie: presupunem propozit ia adev arat a p an a la n 1
si demonstr am c a si P(n) este adev arat a. Fie A
1...n
= (A
1...p
A
p+1...n
), 1 p < n. Atunci: conform propozit iei P(p) avem
c a num arul de perechi de paranteze pentru A
1...p
este p 1, iar
pentru A
p...n
este n (p + 1). Pentru A
1...n
avem nevoie de (p
174
1) + (n p 1) + 1 perechi de paranteze (ultimul termen din
sum a se datoreaz a perechii de paranteze exterioare). Deci P(n)
este adev arat a, de unde concluzia din enunt ul problemei.
(c) Problema 3. Relat ia dup a care se calculeaz a optimul este:
m(i, j) = min
ik<j
m(i, k) +m(k + 1, j) +p
i1
p
k
p
j
(B.11)
Fie . m(, ) este accesat n cadrul (B.11) e ca m(i, k), e
ca m(k + 1, j). Fie t(, ) num arul de apeluri ce se face pentru
m(, ) n primul caz si T(, ) num arul de apeluri ce rezult a
din al doilea caz.
Pentru primul caz, avem i = , k = . Putem avea j +1, n,
deci T(, ) = n . Pentru U(, ) se poate r ata analog c a
U(, ) = n . Obt inem:
R(, ) = T(, ) =
n
=1
n
=
(n + 1) = =
n
3
n
3
(d) Problema 4. Fie a = (a(i, j)) matricea triunghiular a dat a la in-
trare (1 i n, 1 j i). Observ am c a avem 2
n1
posibilit at i
de a forma drumuri de la a(1, 1) la ultima linie (demonstrat ia se
face prin induct ie matematic a dup a n). Ca atare, o metod a de
abordare de tip brute force este de la nceput sortit a esecului.
De asemenea se observ a c a o strategie de tipul coboar a la num arul
cel mai mare aat pe linia imediat urm atoare nu duce la solut ie
optim a. Vom da un algoritm bazat pe programare dinamic a.
Fie T drumul de la a(1, 1) la ultima linie care d a suma mai-
xim a. Fie S(i, j) un element de pe acest drum, aat pe linia i
si coloana j. Atunci S(i, j) este valoarea maxim a care se poate
obt ine plec and din (i, j) p an a la ultima linie. Dac a nu ar asa,
atunci nseamn a c a ar exista un alt drum de la (i, j) la ultima
linie care d a valoare mai mare, iar prin modicarea lui T astfel
nc at s a includ a acest ultim drum am obt ine o valoare mai mare,
contradict ie cu alegerea lui T. Ca atare, putem deduce c a:
S(i, j) =
_
S(n, j) dac a i = n
a(i, j) + maxS(i + 1, j), S(i + 1, j + 1) dac a i < n
(B.12)
pentru 1 i n, 1 j i; ceea ce ne duce la algoritm. Calculul
lui S(i, j) nu se face recursiv, ci folosind o matrice triunghiular a.
175
Pentru reconstituirea solut iei se foloseste o matrice triunghilar a
sol
Start Triunghi
citeste( n, (a(i, j), i = 1, n, j = 1, i) )
pentru j = 1, n
s(n, j) = a(n, j)
sf arsit pentru
pentru i = n 1, 1, 1
pentru j = 1, i
dac a s(i + 1, j) > s(i + 1, j + 1) atunci
s(i, j) = a(i, j) +s(i + 1, j)
sol(i, j) = j
altfel
s(i, j) = a(i, j) +s(i + 1, j)
sol(i, j) = j + 1
sf arsit dac a
sf arsit pentru
sf arsit pentru
scrie( Suma maxim a este, s(1, 1) )
scrie( Ea se obt ine astfel: )
i = j = 1
scrie( a(1, 1) )
pentru k = 1, n 1
j = sol(i, j)
i = i + 1
scrie( a(i, j) )
sf arsit pentru
Stop
3. Problema 5. Suger am cititorului s a urm areasc a rezolvarea problemei
1. Rezolvarea se bazeaz a pe un algoritm de tip Divide et Impera din
cauz a c a pentru un produs de tipul A
i...j
vom determina indicele k
pentru care facem descompunerea A
i...j
= (A
i...k
) (A
k+1...j
), ecare din
cele dou a matrici ind la r andul lor parantezate independent, p an a
c and se ajunge la c ate o singur a matrice.
Descompunere(s.i, j)
dac a i = j atunci
scrie( i )
Return
sf arsit dac a
dac a j i = 1 atunci
176
scrie( (, i,*, j, ) )
Return
sf arsit dac a
k = s(i, j)
scrie( ( )
Inmultiri(s, i, k)
scrie( )*( )
Inmultiri(s, k + 1, j)
scrie( ) )
Return
Propunem cititorului interesat crearea unui algoritm care s a determine
toate modalit at ile de nmult ire a matricelor astfel nc at s a se ajung a la
un num ar de nmult iri scalare minim. (Indicat ie: nu se mai foloseste
informat iua din s, ci doar cea din m)
177
178
Bibliograe
[1] Andonie, R azvan, and G arbacea, Ilie. Algoritmi fundamentali. O perspec-
tiv a C++. Editura Libris, 1995. Download de la: http://vega.unitbv.ro/
andonie.
[2] Cormen, Thomas H, Leiserson, E Charles, and Rivest, Ronald R. Intro-
ducere n algoritmi. Computer Libris Agora, 2000.
[3] Livovschi, Leon and Georgescu, Horia. Sinteza si analiza algoritmilor.
Editura Stiint ic a si Enciclopedic a, 1986.
[4] Tudor, Sorin. Tehnici de programare (Manual pentru clasa a X-a). L&S
Infomat, 1996.
179