ALGORITMILOR
AU
Tematica
1 Elemente de complexitatea algoritmilor
1.1 Notatii asimptotice . . . . . . . . . . . .
1.2 Exemple si proprietati . . . . . . . . . .
1.3 Analiza algoritmilor . . . . . . . . . . . .
1.4 Determinarea maximului dintr-un vector
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
11
15
22
2 Metoda Greedy
2.1 Descrierea metodei. Algoritmi generali . . . . . . .
2.2 O problema de maxim/minim . . . . . . . . . . . .
2.3 Memorarea optimala a textelor pe benzi . . . . . .
2.4 Problema rucsacului, varianta continua . . . . . . .
2.5 Problema planificarii spectacolelor . . . . . . . . . .
2.6 Arbori partiali de cost minim . . . . . . . . . . . .
2.7 Distante si drumuri minime. Algoritmul lui Dijkstra
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
30
33
35
42
49
55
3 Metoda Backtracking
3.1 Descrierea metodei. Algoritmi generali
3.2 Colorarea grafurilor . . . . . . . . . . .
3.3 Problema celor n dame pe tabla de sah
3.4 Problema nebunilor pe tabla de sah . .
3.5 Generarea obiectelor combinatoriale . .
3.5.1 Preliminarii . . . . . . . . . . .
3.5.2 Produs cartezian . . . . . . . .
3.5.3 Submultimi . . . . . . . . . . .
3.5.4 Aranjamente cu repetitie . . . .
3.5.5 Aranjamente . . . . . . . . . .
3.5.6 Permutari . . . . . . . . . . . .
3.5.7 Combinari . . . . . . . . . . . .
3.5.8 Combinari cu repetitie . . . . .
3.5.9 Permutari cu repetitie . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
64
64
72
75
79
88
88
89
90
92
92
96
98
100
102
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
TEMATICA
4 Metoda Divide et Impera
4.1 Descrierea metodei. Algoritmi generali . . .
4.2 Complexitatea metodei. Teorema Master . .
4.3 Problema turnurilor din Hanoi . . . . . . . .
4.4 Cautarea binara . . . . . . . . . . . . . . . .
4.5 Algoritmi de sortare . . . . . . . . . . . . .
4.5.1 Problema sortarii . . . . . . . . . . .
4.5.2 Interclasarea a doi vectori . . . . . .
4.5.3 Sortarea prin interclasare (mergesort)
4.5.4 Sortarea rapida (quicksort) . . . . . .
4.6 O problema de acoperire . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Metoda program
arii dinamice
5.1 Descrierea metodei. Algoritm general . . . . . . . . . . . . .
5.2 Problema subsirului crescator de lungime maxima . . . . . .
5.3 Problema drumului de suma maxima/minima ntr-o matrice
.
.
.
.
.
.
.
.
.
.
107
107
110
118
121
131
131
135
138
148
160
164
. 164
. 165
. 173
Evaluare
Prezenta: 10%
Activitate laborator: 30% (Programe si probleme din Temele de laborator)
Teme de casa: 10% (Programe si probleme suplimentare)
Examen final: 50% (Proba scrisa: teorie, algoritmi -cu implementaresi probleme)
Bibliografie
[1] A.V. Aho, J.E. Hopcroft, J.D. Ullman, Data Structures and Algorithms, AddisonWesley, Massachusetts, 2009.
[2] Gh. Barbu, V. P
aun, Programarea n limbajul C/C++, Editura Matrix Rom, Bucuresti, 2011.
[3] Gh. Barbu, V. P
aun, Calculatoare personale si programare n C/C++, Editura Didactic
a si Pedagogic
a, Bucuresti, 2005.
[4] Gh. Barbu, I. V
aduva, M. Bolosteanu, Bazele informaticii, Editura Tehnica, Bucuresti, 1997.
[5] C. Balc
au, Combinatoric
a si teoria grafurilor, Editura Universitatii din Pitesti,
Pitesti, 2007.
[6] O. Basc
a, L. Livovschi, Algoritmi euristici, Editura Universitatii din Bucuresti, Bucuresti, 2003.
[7] E. Cerchez, M. Serban, Programarea n limbajul C/C++ pentru liceu. Vol. 2: Metode
si tehnici de programare, Ed. Polirom, Iasi, 2005.
[8] E. Ciurea, L. Ciupal
a, Algoritmi. Introducere n algoritmica fluxurilor n retele, Editura Matrix Rom, Bucuresti, 2006.
[9] T.H. Cormen, Algorithms Unlocked, MIT Press, Cambridge, 2013.
[10] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein, Introduction to Algorithms, MIT
Press, Cambridge, 2009.
[11] C. Croitoru, Tehnici de baz
a n optimizarea combinatorie, Editura Universitatii Al.
I. Cuza, Iasi, 1992.
[12] N. Dale, C. Weems, Programming and problem solving with JAVA, Jones & Bartlett
Publishers, Sudbury, 2008.
[13] D. Du, X. Hu, Steiner Tree Problems in Computer Communication Networks, World
Scientific Publishing Co. Pte. Ltd., Hackensack, 2008.
[14] S. Even, Graph Algorithms, Cambridge University Press, Cambridge, 2012.
5
[15] H. Georgescu, Tehnici de programare, Editura Universitatii din Bucuresti, Bucuresti,
2005.
[16] C.A. Giumale, Introducere n analiza algoritmilor. Teorie si aplicatii, Ed. Polirom,
Iasi, 2004.
[17] F.V. Jensen, T.D. Nielsen, Bayesian Networks and Decision Graphs, Springer, New
York, 2007.
[18] D. Jungnickel, Graphs, Networks and Algorithms, Springer, Heidelberg, 2013.
[19] D.E. Knuth, The Art Of Computer Programming. Vol. 4A: Combinatorial Algorithms, Addison-Wesley, Massachusetts, 2011.
[20] B. Korte, J. Vygen, Combinatorial Optimization. Theory and Algorithms, Springer,
Heidelberg, 2012.
[21] L. Livovschi, H. Georgescu, Sinteza si analiza algoritmilor, Editura Stiintific
a si
Enciclopedica, Bucuresti, 1986.
[22] D. Logofatu, Algoritmi fundamentali n C++: Aplicatii, Ed. Polirom, Iasi, 2007.
[23] D. Logofatu, Algoritmi fundamentali n Java: Aplicatii, Ed. Polirom, Iasi, 2007.
[24] D. Lucanu, M. Craus, Proiectarea algoritmilor, Ed. Polirom, Iasi, 2008.
[25] D.R. Popescu, Combinatoric
a si teoria grafurilor, Societatea de Stiinte Matematice
din Rom
ania, Bucuresti, 2005.
[26] N. Popescu, Data structures and algorithms using Java, Editura Politehnica Press,
Bucuresti, 2008.
[27] V. Preda, C. Balc
au, Entropy optimization with applications, Editura Academiei
Rom
ane, Bucuresti, 2010.
[28] R. Sedgewick, K. Wayne. Algorithms, Addison Wesley, Massachusetts, 2011.
[29] R. Stephens, Essential Algorithms: A Practical Approach to Computer Algorithms,
Wiley, Indianopolis, 2013.
[30] S. T
anasa, C. Olaru, S. Andrei, Java de la 0 la expert, Ed. Polirom, Iasi, 2007.
[31] T. Toadere, Grafe. Teorie, algoritmi si aplicatii, Editura Albastr
a, Cluj-Napoca,
2002.
[32] I. Tomescu, Combinatoric
a si teoria grafurilor, Tipografia Universitatii din Bucuresti, Bucuresti, 1978.
[33] I. Tomescu, Probleme de combinatoric
a si teoria grafurilor, Editura Didactica si
Pedagogic
a, Bucuresti, 1981.
[34] I. Tomescu, Data structures, Editura Universitatii din Bucuresti, Bucuresti, 2004.
6
[35] ***, Handbook of combinatorics, edited by R.L. Graham, M. Grotschel and L. Lovasz,
Elsevier, Amsterdam, 1995.
[36] ***, Handbook of discrete and combinatorial mathematics, edited by K.H. Rosen,
J.G. Michaels, J.L. Gross, J.W. Grossman and D.R. Shier, CRC Press, Boca Raton,
2000.
Tema 1
Elemente de complexitatea
algoritmilor
1.1
Notatii asimptotice
Vom defini un tip de functii care reprezinta un bun model pentru descrierea
complexitatii temporale a unui algoritm, adica a dependentei timpului de
executie fata de dimensiunea datelor de intrare.
Definitia 1.1.1. O functie asimptotic pozitiv
a (prescurtat a.p.) este o
functie f : N \ A R a..
A N este o multime finita;
n0 N \ A astfel ncat f (n) > 0, n n0 .
Observatia 1.1.1. De cele mai multe ori, multimea A este de forma
A=
{0, 1, 2, . . . , k} , unde k N.
{z
}
|
(3n4 + n + 3) n 5
Exemplul 1.1.1. Functia f : D R, f (n) =
, unde
(5n + 1)(n 8)
D = {n N | n 5, n 6= 8}, este asimptotic pozitiva, deoarece D = N \ A
cu A = {0, 1, 2, 3, 4, 8} (multime finita) si f (n) > 0, n 9.
ln(n5 + 1) n
, nu este
(n 1)(n 6)
asimptotic pozitiva, deoarece (n 1)(n 6) > 0, n 7, dar lim [ln(n5 +
Exemplul 1.1.2. Functia g : N \ {1, 6} R, g(n) =
f (n)
= 1.
n g(n)
lim
Figura 1.1.1:
10
Figura 1.1.2:
Figura 1.1.3:
11
Notatia se foloseste pentru a exprima complexitatea unui algoritm corespunzatoare timpului de executie n cazul cel mai favorabil.
Notatia se foloseste atunci cand se poate determina exact timpul de
executie al unui algoritm sau atunci cand timpii de executie corespunzatori
cazurilor extreme sunt exprimati prin functii care au acelasi ordin de crestere.
1.2
Exemple si propriet
ati
(1.2.1)
(1.2.2)
(1.2.3)
12
f (n)
c, n n3 .
g(n)
0 lim
f (n)
g(n)
nN
f (n)
M, n N.
g(n)
Prin nmultire cu g(n) > 0, obtinem ca
f (n) M g(n), n N,
deci f (n) = O (g(n)).
b) Fie f (n) = (g(n)), deci
c > 0 si n0 N a.. c g(n) f (n), n n0 .
Fie n3 = max {n0 , n2 }. Impartind cu g(n) > 0 rezulta ca
0<c
f (n)
, n n3 .
g(n)
(1.2.4)
13
f (n)
,
g(n)
(1.2.5)
lim
= lim
=
n f (n)
n f (n)
0, daca = +,
g(n)
deci
g(n)
[0, +).
n f (n)
lim
f (n) = (g(n))
(0, +]
f (n) = (g(n))
[0, +) (0, +] (0, +).
Exemplul 1.2.1. Vom aplica propozitia anterioar
a pentru functia asimptotic
(3n4 + n + 3) n 5
, unde D = {n N | n
pozitiva f : D R, f (n) =
(5n + 1)(n 8)
5, n 6= 8}, considerata n Exemplul 1.1.1.
Deoarece
f (n)
(3n4 + n + 3) n 5
lim
= lim
n n3
n n3 (5n + 1)(n 8)
q
n4 n 3 + n13 + n34
1 n5
= lim
= 0,
n
n5 (5 + n1 )(1 n8 )
14
f (n)
(3n4 + n + 3) n 5
lim
= lim
n n2
n n2 (5n + 1)(n 8)
q
n4 n 3 + n13 + n34
1 n5
= lim
= ,
n
n4 (5 + n1 )(1 n8 )
rezulta ca f (n) = (n2 ), dar f (n) 6= O (n2 ) si f (n) 6= (n2 ).
Deoarece
f (n)
(3n4 + n + 3) n 5
lim
= lim 2
n n2 n
n n
n(5n + 1)(n 8)
q
1 n5
n4 n 3 + n13 + n34
3
= ,
= lim
8
1
4
n
5
n n(5 + n )(1 n )
rezulta ca f (n) = (n2 n), deci f (n) = O (n2 n) si f (n) = (n2 n).
Propozitia 1.2.3. Fie f si g doua functii asimptotic pozitive. Daca f g,
atunci f (n) = (g(n)).
f (n)
= 1 (0, ), deci conform
n g(n)
propozitiei anterioare rezulta ca f (n) = (g(n)).
Demonstratie. Daca f g, atunci lim
= lim
a) Pentru k p avem
=
0,
ap ,
daca k > p,
daca k = p,
15
l = lim
1.3
Analiza algoritmilor
Definitia 1.3.1. Un algoritm pentru rezolvarea unei probleme este o secventa finita de propozitii (declaratii ale datelor utilizate si instructiuni
aplicabile acestor date) prin aplicarea carora se trece de la informatia initial
a (datele de intrare, parametrii problemei) la informatia final
a
(datele de ie
sire, rezultatele problemei), cu respectarea urmatoarelor
caracteristici:
1) generalitatea: algoritmul este aplicabil pentru orice set de valori ale
datelor de intrare, compatibile cu problema;
2) unicitatea (neambiguitatea): pentru orice set fixat de valori ale
datelor de intrare (din domeniul de aplicabilitate al problemei) succesiunea instructiunilor aplicate este univoc determinata de algoritm
(adica nu depinde de alti factori precum locul sau momentul aplicarii);
3) finitudinea: pentru orice set de valori ale datelor de intrare aplicarea
algoritmului se termina dupa un numar finit de pasi, adica dupa executarea unei succesiuni finite de instructiuni.
Definitia 1.3.2. Un algoritm este corect daca pentru orice set de valori
ale datelor de intrare (din domeniul de aplicabilitate) rezultatele obtinute la
terminarea aplicarii algoritmului sunt corecte.
16
17
18
INTERSCHIMBARE2(a, b) :
a a + b;
b a b;
a a b;
Analiza algoritmului:
a) resurse hardware: 2 locatii de memorie;
b) operatii efectuate:
3 atribuiri;
3 adunari si scaderi.
Observam ca Varianta 2 utilizeaza mai putine locatii de memorie, dar
mai multe operatii.
Exemplul 1.3.2. Calculul produsului a doua numere complexe z1 , z2 C. Fie
z1 = a1 + b1 i,
z2 = a2 + b2 i, cu a1 , a2 , b1 , b2 R,
sau, altfel scris,
z1 = (a1 , b1 ),
z2 = (a2 , b2 ).
Atunci
z1 z2 = (a1 + b1 i) (a2 + b2 i) =
= a1 a2 b1 b2 + (a1 b2 + a2 b1 ) i,
{z
} |
|
{z
}
partea real
a
partea imaginar
a
z1 z2 = (a1 a2 b1 b2 , a1 b2 + a2 b1 ).
{z
} |
{z
}
|
p
Varianta 1:
19
PRODUS1(a1 , b1 , a2 , b2 , p, q) :
citeste a1 , b1 , a2 , b2 ;
t1 a1 a2 ;
t2 b1 b2 ;
p t1 t2 ;
t1 a1 b2 ;
t2 a2 b1 ;
q t1 + t2 ;
afiseaz
a p, q;
Analiza algoritmului:
a) resurse hardware: 4 + 2 + 2 = 8 locatii de memorie;
b) operatii efectuate:
4 nmultiri;
2 adunari si scaderi;
6 atribuiri;
Varianta 2: Rescriem expresiile pentru partile reala si imaginara astfel:
p = a1 a2 b1 b2 = (a1 + b1 ) a2 b1 (a2 + b2 ),
q = a1 b2 + a2 b1 = (a1 + b1 ) a2 + a1 (b2 a2 ).
PRODUS2(a1 , b1 , a2 , b2 , p, q) :
citeste a1 , b1 , a2 , b2 ;
t1 a1 + b1 ;
t2 t1 a2 ;
t1 a2 + b2 ;
t3 b1 t1 ;
p t2 t3 ;
t1 b2 a2 ;
t3 a1 t1 ;
q t2 + t3 ;
afiseaz
a p, q;
Analiza algoritmului:
a) resurse hardware: 4 + 2 + 3 = 9 locatii de memorie;
b) operatii efectuate:
3 nmultiri;
20
5 adunari si scaderi;
8 atribuiri;
Observam ca Varianta 2 utilizeaza mai putine nmultiri, dar mai multe locatii
de memorie, mai multe adunari si scaderi si mai multe atribuiri.
Observatia 1.3.4. In analiza performantelor algoritmilor, este esential tipul
de masin
a pe care acestia vor rula:
masin
a secvential
a (masin
a cu acces aleator, Random Access Machine = RAM), n care toate prelucrarile sunt executate secvential;
masin
a paralel
a (de regula, un sistem de calcul multiprocesor ), n care
se pot executa simultan (n paralel) portiuni ale aceluiasi algoritm.
Observatia 1.3.5. Pentru analiza algoritmilor ce vor fi prezentati n continuare, stabilim urmatoarele conventii:
vom lucra cu algoritmi secventiali (nu paraleli ), destinati a fi implementati pe masini secventiale;
n general, ne vom referi numai la analiza timpului de executie (complexitatea temporal
a);
timpul de executie al oricarei operatii elementare nu depinde de valorile operanzilor (timpul de executie pentru a calcula 1+2 nu difera de
timpul de executie pentru a calcula 12345+6789);
timpul necesar accesarii datelor nu depinde de locatia acestora n memorie (nu este diferenta ntre timpul necesar prelucrarii primului element al unui tablou si cel al prelucrarii penultimului element);
De asemenea, pentru simplificarea calculelor, de cele mai multe ori ne
vom concentra atentia numai asupra anumitor operatii, semnificative pentru
algoritmii respectivi, rezumandu-ne astfel numai la estimarea (numararea)
acestora.
Definitia 1.3.5. Fie A un algoritm, n dimensiunea datelor de intrare si
T (n) timpul de executie estimat pentru algoritmul A.
Ordinul de complexitate al algoritmului (complexitatea algoritmului) A este ordinul (de crestere) al functiei T (n) (cand n ).
21
22
1.4
Problema determin
arii maximului dintr-un vector este urmatoarea:
Se considera un vector A = (a1 , a2 , . . . , an ), n 1. Se cere sa se determine
maximul dintre elementele a1 , a2 , . . . , an si prima pozitie pe care acesta apare,
adica perechea (m, k), unde
m = max{ai | 1 i n},
k = min{i | 1 i n, ai = m}.
Observatia 1.4.1. In practica, problema consta n gasirea primei nregistrari
ntr-un fisier sau baza de date dupa valoarea maxima a unui camp, numit
cheie.
Algoritmul 1.4.1 (Determinarea maximului dintr-un vector). Descrierea
n pseudocod a algoritmului are urmatoarea forma.
MAX(A, n, m, k) :
// Timp de executie
Nr. de executii
k 1;
//
c1
1
m A[1];
//
c2
1
//
c3
n
for i = 2, n do
if m < A[i] then
//
c4
n1
m A[i];
//
c2
?
k i;
//
c1
?
Analiza complexit
atii algoritmului:
1) Timpul de executie n cazul cel mai favorabil, si anume cand elementul a1
este maxim:
Tf av (n) = 1 c1 + 1 c2 + n c3 + (n 1) c4 + 0 (c2 + c1 )
= (c3 + c4 ) n + (c1 + c2 c4 ) .
| {z }
{z
}
|
constant
a
constant
a
Rezulta ca
T (n) = (n).
(1.4.1)
2) Timpul de executie n cazul cel mai defavorabil si anume cand a1 < a2 <
< an :
Tdef (n) = 1 c1 + 1 c2 + n c3 + (n 1) c4 + (n 1) (c2 + c1 )
= (c1 + c2 + c3 + c4 ) n + (c4 ) .
| {z }
{z
}
|
constant
a
constant
a
23
Rezulta ca
T (n) = O (n).
(1.4.2)
(1.4.3)
24
i=n
n1
Ai1
Anp
(n 1)!
p
P
i=n
n! Cpn
n1
Ci1
(n 1)! Cpn
1
= ,
n
n! Cp
n
Tmed (n) =
n
P
Tj (n)
j=1
Dar
Tj (n) 1 c1 + 1 c2 + n c3 + (n 1) c4 + (j 1) (c2 + c1 )
= (c3 + c4 ) n + (c1 + c2 ) j c4 .
Atunci
Tmed (n)
=
n
P
(c3 + c4 ) n + (c1 + c2 ) j c4
j=1
(c3 + c4 ) n2 + (c1 + c2 )
n
(c3 + c4 ) n2 + (c1 + c2 )
n
P
j=1
j c4 n
n (n + 1)
c4 n
2
n+1
c4
= (c3 + c4 ) n + (c1 + c2 )
2
c1 + c2
c1 + c2
=
+ c3 + c4 n +
c4
2
2
|
|
{z
}
{z
}
constant
a
constant
a
25
In toate cele trei variante, s-a obtinut o dependenta liniara a timpului de executie fata de dimensiunea datelor de intrare. Astfel am justificat
urmatorul rezultat.
Propozitia 1.4.1. Algoritmul 1.4.1 are complexitatea (n), deci este un
algoritm liniar.
Observatia 1.4.2. O justificare imediata a acestui rezultat este data de relatia
(1.4.3), deci nu necesita o estimare mai buna a timpului de executie mediu.
Am dorit, nsa, si o exemplificare a modului de evaluare a acestui timp.
Observatia 1.4.3. In contextul evaluarii de mai sus a timpului de executie
mediu n cazul n care domeniul este o multime finita, daca renuntam la
presupunerea ca elementele vectorului sunt distincte doua cate doua, atunci
probabilitatea ca primul indice pe care maximul apare n vectorul A sa fie
j nu mai este aceeasi pentru toti indicii j {1, 2, . . . , n}. Intr-adevar, sa
consideram din nou ca multimea are p elemente {b1 , b2 , . . . , bp }, cu b1 <
b2 < . . . < bp , p N . Acum vectorul A = (a1 , a2 , . . . , an ) poate fi ales
n pn moduri, iar, pentru orice j {1, 2, . . . , n}, cazurile n care j este
primul indice pe care maximul apare n vectorul A sunt cele n care exista i {1, 2, . . . , p} astfel ncat aj = bi , a1 , . . . aj1 {b1 , b2 , . . . , bi1 } si
aj+1 , . . . , an {b1 , b2 , . . . , bi }, deci numarul acestor cazuri este egal cu
p
X
i=1
(i 1)j1 inj
tj =
p
P
i=1
(i 1)j1 inj
pn
tj tj+1 =
p
P
i=1
(i 1)j1 inj1
pn
26
Optimalitatea algoritmului:
Vom analiza eficienta algoritmului prin prisma numarului de comparatii efectuate si care invoca elemente ale vectorului.
Evident, Algoritmul 1.4.1 efectueaza n1 asemenea comparatii, de forma
m < A[i].
Din acest punct de vedere, rezultatul urmator justifica optimalitatea acestui algoritm.
Propozitia 1.4.2. Pentru determinarea maximului dintre n numere, n
N , sunt necesare n 1 comparatii.
Demonstratie. Notam proprietatea din enunt cu P (n) si i demonstram valabilitatea prin inductie dupa n.
P (1): Pentru n = 1 sunt necesare 0 = 1 1 comparatii, deci P (1) este
adevarata.
P (k 1) P (k): Fie k N, k 2. Presupunem afirmatia adevarata
pentru orice k 1 numere si o demonstram pentru k numere.
Fie a1 , a2 , ..., ak1 , ak aceste numere.
Fie ai si aj , i 6= j, numerele care sunt supuse primei comparatii.
Presupunem ca ai aj (rationamentul este similar n cazul cand aj ai ).
Atunci
max{a1 , a2 , ..., ak1 , ak } = max{a1 , a2 , ..., aj1, aj+1 , ..., ak1 , ak },
adica avem de determinat n continuare maximul dintre k 1 numere (celelalte k 2 numere si ai ). Pentru aceasta, conform ipotezei de inductie, sunt
necesare nca k 2 comparatii. Deci obtinem un total de 1 + (k 2) = k 1
comparatii.
Demonstratia prin inductie este astfel ncheiata.
Urmatorul rezultat este o consecinta directa a propozitiei anterioare.
Propozitia 1.4.3. Algoritmul 1.4.1 este optim (n clasa algoritmilor bazati
pe comparatii de chei).
Tema 2
Metoda Greedy
2.1
27
28
Daca includerea elementului ales n solutia partiala construita anterior conduce la o solutie posibila, atunci construim noua solutie prin
adaugarea elementului ales.
GREEDY1(A, n, B) :
B ;
for i = 1, n do
x ALEGE(A, i, n);
if SOLUTIE POSIBILA (B, x) then
B B {x};
Observatia 2.1.1.
Functia ALEGE(A, i, n) returneaza un element x = aj {ai , . . . , an }
si efectueaza interschimbarea ai aj ;
Functia SOLUTIE POSIBILA(B, x) verifica daca B{x} este solutie
posibila a problemei.
Functia ALEGE este cea mai dificil de realizat, deoarece trebuie sa
implementeze criteriul conform caruia alegerea la fiecare pas a cate
unui candidat sa conduca n final la obtinerea solutiei optime.
Algoritmul 2.1.2 (Metoda Greedy, varianta a II-a).
Metoda e asemanatoare primeia, cu exceptia faptului ca se stabileste de
la nceput ordinea n care trebuie analizate elementele din A.
GREEDY2(A, n, B) :
PRELUCREAZA (A, n);
B ;
for i = 1, n do
if SOLUTIE POSIBILA (B, ai ) then
B B {ai };
Observatia 2.1.2. Prin apelul procedurii PRELUCREAZA(A, n) se efectueaza o permutare a elementelor multimii A, stabilind ordinea de analiza a
acestora. Aceasta este procedura cea mai dificil de realizat.
Observatia 2.1.3.
29
bB\{b0 }
30
2.2
// adev
arat
// fals
O problem
a de maxim/minim
b)
n
X
i=1
k=1
n
X
k=1
Sn
k=1
ak bnk+1 = min
Sn
n
X
k=1
ak b(k) .
n
X
k=1
ak b(k) .
31
n
X
k=1
ak b(k) ,
(2.2.1)
(2.2.2)
(Obs. Pentru permutarea identica, e Sn , avem e(i) < e(j) , i < j).
|{z} |{z}
i
(2.2.3)
,
=
(1) (2) . . . (j) . . . (i) . . . (n)
adica
(k) = (k), k cu k 6= i si k 6= j,
(i) = (j),
(j) = (i).
Calculam
S() S( ) =
n
X
k=1
ak b(k)
n
X
k=1
ak b (k) =
32
In continuare, daca 6= e, se reia rationamentul precedent pentru permutarea , obtinandu-se o permutare pentru care
S() = S( ) = S( ).
Dupa un numar finit de pasi, se va obtine permutarea identica e pentru care
vom avea ca
n
n
X
X
ak bk .
ak be(k) =
S() = S(e) =
k=1
k=1
T
inand seama de relatia (2.2.1), obtinem ca
n
X
k=1
ak bk = max
Sn
n
X
k=1
ak b(k) .
ak bnk+1
n
X
k=1
ak b(k)
n
X
k=1
ak bk .
cel mai mic dintre termenii sirului (bj )j=1,n neales la pasii precedenti.
33
2.3
Memorarea optimal
a a textelor pe benzi
k
X
i=1
Tmediu =
n
X
k=1
Tk
=
n X
k
X
k=1 i=1
Lp(i)
.
34
n X
k
X
n X
k
X
Lp(i) . Atunci
k=1 i=1
Lp(i) =
k=1 i=1
n
X
k=1
Lp(1) + Lp(2) + + Lp(k) =
= Lp(1) + Lp(1) + Lp( 2) + + Lp(1) + Lp(2) + + Lp(n) =
= n Lp(1) + (n 1) Lp(2) + + 2 Lp(n1) + 1 Lp(n) =
n
X
(n k + 1) Lp(k) .
=
k=1
n
X
k=1
n
X
k=1
(n k + 1) Le(k) =
n
X
k=1
(n k + 1) Lk =
Lk (n k + 1).
35
2.4
n
X
xi ci .
i=1
gi G.
(2.4.1)
36
xi gi = G
(2.4.2)
i=1
i=1
i=1
1
u = min 1 xk ,
gk
avem u > 0, xk 1,
si f (x ) =
n
P
i=1
xi ci =
n
P
i=1
n
P
i=1
xi gi =
n
P
i=1
n
X
xi gi
i=1
xi gi +ugk
n
P
i=1
!)
xi gi +G
n
P
i=1
xi gi = G
.
g1
g2
gn
(2.4.3)
37
RUCSAC (G, n, g, c, x, C) :
// g = (g1 , . . . , gn ), c = (c1 , . . . , cn )
// C = c^
as
tigul total
SORTARE(g, c, n);
// se sorteaz
a obiectele descresc
ator
// dup
a c^
as
tigul lor unitar
R G;
// R = greutatea disponibil
a pentru rucsac
C 0;
i 1;
while R > 0 do
// rucsacul nu este plin
if g[i] R then
// obiectul curent ^
ncape ^
n ^
ntregime, deci
// se adaug
a
^n rucsac
x[i] 1;
C C + c[i];
R R g[i];
// actualiz
am greutatea disponibil
a
i i + 1;
// trecem la obiectul urm
ator
else
// obiectul curent nu ^
ncape ^
n ^
ntregime, deci
// se adaug
a exact acea parte din el care
// umple rucsacul
si ^
nc
arcarea se
^ncheie
R
x[i] g[i] ;
C C + x[i]c[i];
R 0;
for j = i + 1, n do x[i] 0;
AFISARE(C, x, n);
// se afi
seaz
a c^
as
tigul total maxim C
//
si solut
ia optim
a x = (x1 , . . . , xn )
Teorema 2.4.1 (de corectitudine a Algoritmului 2.4.1). In contextul Algoritmului 2.4.1, vectorul x = (x1 , . . . , xn ) calculat de algoritm este o
solutie optim
a a problemei rucsacului.
Demonstratie. Evident, vectorul x = (x1 , . . . , xn ) calculat de algoritm verifica
relatiile
(2.4.4)
38
xi gi + xk gk =
xi gi + xk gk
xi gi = G,
i=1
i=1
i=1
n
X
i=1
xi ci =
n1
X
xi ci
+ xn cn >
n1
X
xi ci + xn cn = f (x ),
i=1
i=1
Definim vectorul x = (x
1 , . . . , xn ) prin
(
xi , daca 1 i k,
x
i =
xi , daca k + 1 i n,
(2.4.5)
k
X
i=1
xi gi +
n
X
i=k+1
xi gi G.
(2.4.6)
39
k
X
i=1
h(1) =
k
X
xi gi G
n
X
xi gi +
i=1
n
X
i=1
n
X
i=1
xi gi G = G G = 0,
xi gi
i=k+1
G =
k1
X
xi gi
+ xk gk +
i=1
n
X
i=k+1
xi gi G
xi gi xk gk + xk gk G = G + gk (xk xk ) G
= gk (xk xk ) > 0,
iar h este o functie continua pe intervalul [0, 1].
Conform (2.4.5) si (2.4.6) rezulta ca x
si
i [0, 1], i {1, . . . , n}
n
X
x
i gi
k
X
xi gi +
i=1
i=1
n
X
xi gi = h( ) + G = 0 + G = G,
i=k+1
deci vectorul x = (x
ie a problemei.
1 , . . . , xn ) este o solut
Avem
f (x ) f (x ) =
k1
X
xi ci
+ xk ck +
i=1
= xk ck +
= xk ck +
n
X
i=k+1
n
X
i=k+1
n
X
i=k+1
n
X
xi ci
xi ci
n
X
xi ci
i=1
xi ci
i=k
xk ck
= ck (xk xk ) (1 )
=
xi ci
n
X
n
X
xi ci
i=k+1
xi ci
i=k+1
n
X
ck
ci
(xk gk xk gk ) (1 )
xi gi .
gk
g
i
i=k+1
(2.4.7)
(2.4.8)
40
gk
xk gk xk gk
"
ck
xk gk
=
gk
=
ck
gk
ck
=
gk
n
X
i=1
xk gk G +
k
X
k1
X
xi gi
i=1
i=1
i=k+1
xi gi
i=k+1
k1
X
xi gi +
n
X
n
X
xi gi +
i=k+1
xi gi
xi gi +
i=1
n
X
n
X
n
X
!
xi gi
i=k+1
xi gi
i=k+1
xi gi G ,
ck
h( ) = 0,
gk
deci
f (x ) f (x ).
Cum x este solutie optima, rezulta ca si x este solutie optima (si, n plus,
f (x ) = f (x )). Conform (2.4.5) avem
xi = x
i , i {1, . . . , k},
deci relatia (2.4.4) este adevarata pentru k, ceea ce ncheie demonstratia prin
inductie a acestei relatii.
Luand k = n n aceasta relatie rezulta ca exista o solutie optima x =
O1
10
27
O2
7
9
O3
10
40
O4
5
20
O5
6
11
O6
10
20
O7
8
50
O8
15
22
O9
3
4
O10
12
33
41
O7
50
8
O3
40
10
O4
20
5
O10
33
12
O1
27
10
O6
20
10
O5
11
6
O8
22
15
O9
4
3
O2
9
7
5
27 = 156,5.
10
42
2.5
Problema planific
arii spectacolelor
Problema planific
arii spectacolelor este urmatoarea:
Se considera n spectacole S1 , . . . , Sn , n N . Pentru fiecare spectacol Si ,
i {1, . . . , n}, se cunoaste intervalul orar Ii = [ai , bi ] de desfasurare, unde
ai < bi .
O persoana doreste sa vizioneze cat mai multe dintre aceste n spectacole.
Fiecare spectacol trebuie vizionat integral, nu pot fi vizionate simultan mai
multe spectacole, iar timpii necesari deplasarii de la un spectacol la altul sunt
nesemnificativi (egali cu zero).
Se cere sa se selecteze un numar cat mai mare de spectacole ce pot fi
vizionate de o singura persoana, cu respectarea cerintelor de mai sus.
Modelarea problemei
O solutie (solutie posibila ) a problemei este orice submultime P
{I1 , . . . , In } astfel ncat
Ii Ij = , Ii , Ij P, i 6= j
(adica orice submultime de intervale disjuncte doua cte doua).
O solutie optima a problemei este orice solutie P {I1 , . . . , In } astfel
ncat
card (P ) = max{card (P ) | P = solutie a problemei}.
43
(2.5.1)
44
I1 = [a1 , b1 ], I2 = [a2 , b2 ], . . . , Im
= [am , bm ]
(2.5.2)
pentru care
Ii = Ii , i a.. 1 i k.
(2.5.3)
Ii = Ii , i a.. 1 i k 1.
(2.5.4)
45
Ik1
= Ik1
), deci
ak > bk1 .
Atunci, din descrierea algoritmului, deoarece Ik = [ak , bk ] este primul interval
(2.5.5)
(2.5.6)
Ii = [a
,
b
]
=
i
i
Ii , daca i = k.
Deoarece P = {I1 , . . . , Ip } este solutie a problemei si verifica (2.5.2), rezulta
ca
a1 < b1 < a2 < b2 < < ak1 < bk1 < ak < bk <
< ak+1 < bk+1 < < ap < bp .
(2.5.7)
(deoarece Ik1
= Ik1
), deci
ak > bk1 .
(2.5.8)
Din (2.5.7), (2.5.8) si (2.5.5) rezulta ca
a1 < b1 < a2 < b2 < < ak1 < bk1 < ak < bk <
< ak+1 < bk+1 < < ap < bp
(inegalitate valabila si pentru k = 1), deci submultimea P = {I1 , . . . , Ip },
definita de (2.5.6), este o solutie a problemei si
b
1 < b2 < < bp .
46
deci relatia (2.5.3) este adevarata pentru k, ceea ce ncheie demonstratia prin
inductie a acestei relatii.
Luand k = m n aceasta relatie rezulta ca exista o solutie optima P =
{I1 , . . . , Ip } pentru care
Ii = Ii , i {1, . . . , m}.
Demonstram ca p = m prin reducere la absurd. Intr-adevar, daca p > m
Im
= [am , bm ].
Astfel p = m, deci
P = {I1 , . . . , Im
} = {I1 , . . . , Ip } = P
S2
8:10
9:00
S9
11:00
12:30
S3
S4
S5
S6
S7
8:15 8:50 9:10 9:20 9:20
9:00 10:20 10:40 10:30 11:00
S10
S11
S12
S13
S14
12:00 12:10 12:30 13:00 13:40
13:30 14:00 13:50 14:30 15:00
47
S3
8:15
9:00
S9
11:00
12:30
S1
S4
S6
S5
S7
8:00 8:50 9:20 9:10 9:20
9:10 10:20 10:30 10:40 11:00
S10
S12
S11
S13
S14
12:00 12:30 12:10 13:00 13:40
13:30 13:50 14:00 14:30 15:00
48
49
2.6
50
(2.6.1)
51
52
30
50
100
3
20
60
70
90
70
120
5
10
7
100
80
40
9
30
15
110
130
10
Figura 2.6.1:
Aplicarea Algoritmului Kruskal este evidentiata n urmatorul tabel:
Pas
1
2
3
4
5
6
7
8
9
Muchia selectata
[5, 8]
[3, 6]
[1, 2]
[8, 9]
[2, 3]
[2, 5]
[4, 6]
[7, 8]
[4, 10]
Costul ei
10
20
30
30
50
60
90
100
120
Arborele partial de cost minim obtinut este reprezentat n Figura 2.6.2. Costul acestui APM este de 510.
1
30
50
4
20
60
90
120
5
10
7
100
30
Figura 2.6.2:
10
53
Aplicarea Algoritmului Prim pentru acelasi graf este evidentiata n urmatorul tabel:
Pas Muchia selectata Costul ei Nodul selectat
0
1
1
[1, 2]
30
2
2
[2, 3]
50
3
3
[3, 6]
20
6
4
[2, 5]
60
5
5
[5, 8]
10
8
6
[8, 9]
30
9
7
[6, 4]
90
4
8
[8, 7]
100
7
9
[4, 10]
120
10
Arborele partial de cost minim obtinut este deci acelasi cu cel obtinut
prin aplicarea Algoritmului Kruskal.
Observatia 2.6.2. Algoritmii Kruskal si Prim sunt specifici metodei de
programare Greedy. Algoritmul Kruskal selecteaza muchii, n ordinea
crescatoare a costurilor, subgrafurile induse pe parcurs de acestea nefiind
neaparat conexe. Algoritmul Prim selecteaza muchii si noduri, nu neaparat
n ordinea crescatoare a costurilor muchiilor, iar subgrafurile induse pe parcurs de muchiile selectate sunt conexe.
In implementari optime, se poate arata ca Algoritmul Kruskal are complexitatea O (m ln n) (fiind necesara sortarea muchiilor dupa cost), iar Algoritmul Prim are complexitatea O (n2 ) n cazul memorarii grafului prin matricea de adiacenta (o astfel de implementare va fi prezentata n continuare),
unde n si m reprezinta numerele de noduri, respectiv de muchii ale grafului
dat. Graful fiind conex, m n 1.
Pentru grafuri simple, m n(n1)
. Folosind si inegalitatea ln n n 1,
2
obtinem ca Algoritmul Kruskal este mai eficient pentru grafuri sarace n
muchii, iar Algoritmul Prim este mai eficient pentru grafuri bogate n
muchii.
Observatia 2.6.3. Pentru implementarea Algoritmului Kruskal, memoram
graful ponderat conex (G, c), unde G = (V, E), V = {1, . . . , n}, E =
{e1 , . . . , em }, ntr-o matrice cu 3 linii si m coloane P = (pik ) i = 1, 3 avand
k = 1, m
semnificatia:
daca ek = [xk , yk ] E, atunci p1k = xk , p2k = yk si p3k = c(ek ).
54
, n rest,
55
2.7
56
Definitia 2.7.1. Fie (G, c) un graf ponderat, unde G = (V, E), V = {v1 , . . . ,
vn } iar c : E R+ .
a) Daca = (x0 , e1 , x1 , . . . , xk1 , ek , xk ) este un drum al grafului G, unde
x0 , x1 , . . . , xk V , e1 , . . . , ek E, k N, atunci costul (ponderea)
lui este
0, daca k = 0,
k
P
c() =
c(ei ), daca k 1
i=1
57
15
10
10
2
Figura 2.7.1:
Drumurile elementare de la nodul 1 la nodul 5 sunt 1 = (1, 3, 5), avand
costul c(1 ) = 10 + 5 = 15, 2 = (1, 4, 5), avand costul c(2 ) = 5 + 5 = 10,
deci 2 este un drum minim de la 1 la 5. Astfel distanta minima de la nodul
1 la nodul 5 este c(2 ) = 10.
Definitia 2.7.2. Fie (G, c) un graf ponderat, unde G = (V, E), V = {v1 , . . . ,
vn }, c : E R+ .
a) Matricea distantelor (costurilor) directe asociata grafului (G, c)
este matricea C = (cij )i,j=1,n definita prin
0, daca i = j,
min{c(e)|e = (vi , vj ) E}, daca i 6= j si (vi , vj ) E,
cij =
, daca i 6= j si 6 (vi , vj ) E
(pentru grafuri neorientate (vi , vj ) desemnand de fapt muchia [vi , vj ]).
c( ), = drum minim de la vi la vj ,
daca = (vi , . . . , vj ) drum n G,
cij =
, n caz contrar.
Observatia 2.7.5. Evident, pentru orice graf neorientat atat matricea distantelor directe cat si matricea distantelor minime sunt matrice simetrice.
58
0 15 10 5 10
0 15 10 5
0
0
, C = 10 5 0 15 5 .
5
0
5
C=
10 10 20 0 5
10 0 5
5 5 15 10 0
5 5 0
tjk + cjk ik = min{tj + cji |vj {vi1 , . . . , vik1 }, vi V \ {vi1 , . . . , vik1 }}.
(2.7.1)
Se ia
tik = tjk + cjk ik
si se trece la pasul k + 1.
(2.7.2)
59
Teorema 2.7.1 (de corectitudine a Algoritmului Dijkstra). In contextul Algoritmului Dijkstra, avem
ti = csi , i {1, . . . , n}
(adica distanta ti calculata de algoritm este chiar distanta minima de la vs
la vi ).
Demonstratie. Vom demonstra prin inductie dupa k ca nodul vik selectat la
pasul k si distanta corespondenta tik calculata la acel pas verifica egalitatea
din enunt, adica
tik = csik ,
si, n plus, tik < .
Pentru k = 1 afirmatia este evidenta deoarece
vi1 = vs , ti1 = 0 = css .
Presupunem adevarata afirmatia pentru orice pas mai mic decat k si o
demonstram pentru pasul k. Fie vjk {vi1 , . . . , vik1 } un nod ce verifica egalitatea (2.7.1). Din descrierea algoritmului si din ipoteza de inductie (nodul
vjk fiind selectat la un pas anterior), rezulta ca tjk = csjk < si cjk ik < ,
deci tik < (conform (2.7.2)).
Daca (vs , . . . , vjk ) este un drum minim de la vs la vjk (exista, deoarece
csjk < ), atunci = (vs , . . . , vjk , vik ) este un drum de la vs la vik , avand
costul c() = csjk + cjk ik = tjk + cjk ik = tik (conform (2.7.2)), deci
csik tik < .
(2.7.3)
60
(2.7.4)
61
Distanta minima
0
5
10
10
15
62
DIJKSTRA(s) :
for i = 1, n do
// init
ializ
ari
S[i] 0; t[i] ; T AT A[i] ;
t[s] 0; T AT A[s] 0;
// s este nodul surs
a
repeat
// select
am urm
atorul nod x, ^
n ordinea cresc
atoare
// a distant
elor minime de la s la x
min ;
for i = 1, n do
if (S[i] = 0) and (t[i] < min) then
min t[i];
x i;
if (min < ) then
// exist
a x,
^l select
am
S[x] 1;
for i = 1, n do
// actualiz
am vectorii t s
i T AT A
if (S[i] = 0) and (cxi < ) then
if (t[i] > t[x] + cxi ) then
t[i] t[x] + cxi ;
T AT A[i] x;
while (min < );
Exemplul 2.7.4. Pentru graful ponderat din Exemplul 2.6.1, luand ca nod
sursa nodul s = 1, aplicarea Algoritmului Dijkstra este evidentiata n urmatorul
tabel:
Pas Nodul selectat x T AT A[x]
1
1
0
2
2
1
3
5
1
4
3
2
5
8
5
6
6
3
7
7
1
8
9
5
9
4
3
10
10
9
63
30
50
100
20
6
70
110
5
10
7
40
130
10
Figura 2.7.2:
Deci drumurile minime determinate de algoritm sunt:
de la 1 la 1: [1];
de la 1 la 2: [1, 2];
de la 1 la 3: [1, 2, 3];
de la 1 la 4: [1, 2, 3, 4];
de la 1 la 5: [1, 5];
de la 1 la 6: [1, 2, 3, 6];
de la 1 la 7: [1, 7];
de la 1 la 8: [1, 5, 8];
de la 1 la 9: [1, 5, 9];
de la 1 la 10: [1, 5, 9, 10].
Observatia 2.7.10. Implementarea anterioara necesita O (n2 ) operatii (deoarece blocul repeat se executa de cel mult n ori si necesita de fiecare data
cel mult n comparatii pentru determinarea nodului selectat x si cel mult n
comparatii si n adunari pentru actualizarea vectorilor t si T AT A). Aceasta
este de fapt si complexitatea Algoritmului Dijkstra (n implementarea optima) n cazul memorarii grafului prin matricea distantelor directe.
Tema 3
Metoda Backtracking
3.1
65
66
67
68
PRELUCREAZA(x[1], . . . , x[n]);
(*)
// STOP, dac
a se dore
ste
// o singur
a solut
ie rezultat,
// sau k k 1 (revenire fort
at
a) dac
a
// nu mai exist
a valori valide pentru xn
else
k k + 1;
// Avansare
x[k] a[k] r[k];
// preg
atim introducerea
// valorii init
iale ak pentru xk
else
k k 1;
// nu mai exist
a valori netestate pentru xk
// Revenire
69
x[k]
+
r[k];
// C
autare
if (x[1], . . . , x[k]) verifica conditiile de continuare then
k k + 1;
// Avansare
x[k] a[k] r[k];
// preg
atim introducerea
// valorii init
iale ak pentru xk
else
k k 1;
// Revenire
else
PRELUCREAZA(x[1],
. . . , x[n]);
(*)
// STOP, dac
a se dore
ste
// o singur
a solut
ie rezultat
k k 1;
// Revenire, dac
a se doresc
// toate solut
iile rezultat
Observatia 3.1.10. Schemele Backtracking de mai sus genereaza toate solutiile
problemei date. Daca se doreste obtinerea unei singure solutii, atunci n loc
de () se poate insera o comanda de oprire (STOP).
Algoritmul 3.1.3 (Schema Backtracking recursiv
a, varianta 1).
70
// se genereaz
a (x[k], . . . , x[n])
// preg
atim introducerea valorii init
iale
// a[k] pentru x[k]
PRELUCREAZA(x[1],
. . . , x[n]);
else
BACKR1(k + 1);
// Avansare, adic
a
// se genereaz
a, RECURSIV, (x[k + 1], . . . , x[n]).
// La ^
ncheierea apelului BACKR1(k + 1) se produce
// revenirea la funct
ia BACKR1(k)
Apelare: BACKR1(1).
Urmatoarea schema este echivalenta cu cea de mai sus.
Algoritmul 3.1.4 (Schema Backtracking recursiv
a, varianta 2).
BACKR2(k) :
if k n then
x[k] a[k] r[k];
while x[k] < b[k] do
x[k]
x[k] + r[k];
if (x[1], . . . , x[k]) verifica conditiile de continuare then
BACKR2(k + 1);
else
PRELUCREAZA(x[1],
. . . , x[n]);
Apelare: BACKR2(1).
Algoritmul 3.1.5 (Schema Backtracking recursiv
a, varianta 3).
71
BACKR3(k) :
for v = a[k], b[k], r[k] do
// C
autarea lui x[k] ^
n mult
imea Sk
x[k]
v;
if (x[1], . . . , x[k]) verifica conditiile de continuare then
if k = n then
// (x[1], . . . , x[n]) este solut
ie rezultat
PRELUCREAZA(x[1],
. . . , x[n]);
else
BACKR3(k + 1);
// Avansare, adic
a
// se genereaz
a, RECURSIV, (x[k + 1], . . . , x[n]).
// La ^
ncheierea apelului BACKR3(k + 1) se produce
// revenirea la funct
ia BACKR3(k)
Apelare: BACKR3(1).
Urmatoarea schema este echivalenta cu cea de mai sus.
Algoritmul 3.1.6 (Schema Backtracking recursiv
a, varianta 4).
BACKR4(k) :
if k n then
for v = a[k], b[k], r[k] do
x[k]
v;
if (x[1], . . . , x[k]) verifica conditiile de continuare then
BACKR4(k + 1);
else
PRELUCREAZA(x[1],
. . . , x[n]);
Apelare: BACKR4(1).
Observatia 3.1.11. Schemele Backtracking din Algoritmii 3.1.1, 3.1.2, 3.1.3 si
3.1.4 pot fi usor adaptate si pentru situati n care elementele fiecarei multimi
Sk nu sunt n progresie aritmetica.
Observatia 3.1.12. In oricare din cele sase scheme de mai sus, verificarea
(validarea) conditilor de continuare
[(x[1], x[2], . . . , x[k]) verifica conditiile de continuare]
se face adesea prin intermediul unei functii VALID(x, k).
Observatia 3.1.13. Daca, n oricare din cele sase scheme de mai sus, se renunta
la testul
[(x[1], x[2], . . . , x[k]) verifica conditiile de continuare],
72
considerandu-se astfel ca orice solutie posibila verifica conditiile interne, atunci se vor obtine ca solutii rezultat ale problemei toate elementele produsului cartezian S1 S2 Sn .
3.2
Colorarea grafurilor
Problema color
arii grafurilor este urmatoarea:
Se considera un graf neorientat fara bucle G = (V, E), cu multimea
nodurilor
V = {1, 2, . . . , n},
si un numar de m culori, numerotate cu 1, 2, . . . , m.
Se cere sa se determine toate modalitatile de colorare ale nodurilor grafului, utilizand cele m culori, astfel ncat oricare doua noduri adiacente sa fie
colorate cu culori diferite.
Modelarea problemei
Orice solutie a problemei se poate scrie sub forma
x = (x1 , x2 , . . . , xn ),
unde xi este culoarea atasata nodului i, xi {1, 2, . . . , m}.
Avem
x = (x1 , x2 , . . . , xn ) S1 S2 Sn ,
unde
S1 = S2 = = Sn = {1, 2, . . . , m}.
Asadar multimile Sk contin termenii succesivi ai unei progresii aritmetice,
n care
ak = 1,
rk = 1, k = 1, n.
bk = m,
Conditiile interne:
73
Conditiile de continuare:
Daca x1 , . . . , xk1 sunt deja alese, atunci xk verifica conditiile de continuare
(este valid ) daca
xi 6= xk , i {1, . . . , k 1} cu [i, k] E.
Altfel spus, xk nu verifica conditiile de continuare (nu este valid ), daca
exista i {1, 2, . . . , k 1} astfel ncat [i, k] E si xi = xk .
74
Aplicatie: colorarea h
artilor
Problema color
arii h
artilor este urmatoarea:
Se considera o harta si un numar de culori. Se cere sa se coloreze fiecare
tara cu cate una din culori astfel ncat orice doua tari ce au frontiera comuna
sa fie colorate diferit.
Modelarea problemei
Oricarei harti i se poate asocia un graf neorientat simplu astfel:
fiecarei tari i corespunde un nod;
ntre doua noduri exista muchie daca si numai daca ele corespund unor
tari ce au frontiera comuna.
O astfel de corespondenta este evidentiata n Figura 3.2.1.
2
1
1
5
3
5
Figura 3.2.1:
Astfel problema colorarii unei harti se reduce la problema colorarii grafului asociat.
Observatia 3.2.2. Graful asociat unei harti este planar, adica exista o reprezentare grafica n plan a acestuia astfel ncat muchiile sa nu se intersecteze
decat n noduri.
Avem urmatorul rezultat celebru.
Teorema 3.2.1 (Teorema celor 4 culori). Pentru colorarea unui graf
planar sunt suficiente patru culori.
Observatia 3.2.3. Celebritatea problemei colorarii hartilor a constat n faptul
ca n toate exemplele ntalnite colorarea s-a putut face cu numai 4 culori, dar
teoretic se demonstrase ca sunt suficiente 5 culori.
75
3.3
76
Figura 3.3.1:
Pentru cazul general, avem
x = (x1 , x2 , . . . , xn ) S1 S2 Sn ,
unde
S1 = S2 = = Sn = {1, 2, . . . , n}.
ak = 1,
rk = 1, k = 1, n.
bk = n,
Conditiile interne:
77
am revenirea, deoarece
// nu mai exist
a valori valide pentru x[n]
else
k k + 1;
x[k] 0;
else
k k 1;
Functia de verificare (validare) a conditiilor de continuare este
VALID(x, k) :
for i = 1, k 1 do
if (x[k] = x[i] or k i = | x[k] x[i] |) then
returneaz
a 0;
returneaz
a 1;
// fals
// adev
arat
Consideratii
Pentru n = 2 problema nu are solutie, deoarece doua dame asezate
pe linii si coloane diferite se afla pe aceeasi diagonala, deci se ataca
reciproc.
Nici pentru n = 3 problema nu are solutie, deoarece orice doua dame
asezate pe o aceeasi culoare se ataca reciproc.
78
79
3.4
80
(3.4.2)
Modelarea problemei
Cazul 1) Consideram cazul asezarii celor n 1 nebuni pe patratele de culoare
neagra.
Pentru orice solutie rezultat, conform demonstratiei propozitiei anterioare
obtinem ca pe fiecare din cele n 1 diagonale Dk definite prin relatia (3.4.1)
se afla exact un nebun.
Fiecare diagonala Dk , k = 1, n 1. poate fi rescrisa astfel
Dk = {(l, c) | l + c = 2k + 1, 1 l n, 1 c n}
= {(l, 2k + 1 l) | 1 l n, 1 2k + 1 l n}
= {(l, 2k + 1 l) | 1 l n, 2k + 1 n l 2k}
= {(l, 2k + 1 l) | max{2k + 1 n, 1} l min{2k, n}},
deci
hni
,
{(l, 2k + 1 l) | 1 l 2k}, daca 1 k
2
Dk =
h i
81
Figura 3.4.1:
Pentru cazul general, avem
x = (x1 , x2 , . . . , xn1 ) S1 S2 Sn1 ,
unde
h i
{1, 2, . . . , 2k}, daca 1 k n ,
2
h i
Sk =
{2k n + 1, 2k n + 2, . . . , n}, daca n + 1 k n 1.
2
ak = 1,
hni
rk = 1, k = 1,
,
2
bk = 2k,
ak = 2k n + 1,
hni
rk = 1,
k =
+ 1, n 1.
2
bk = n,
82
Conditiile interne:
Pentru orice i 6= j, cei doi nebuni de pe diagonalele Di si Dj , asezati
deci pe liniile xi respectiv xj , si pe coloanele ci = 2i + 1 xi respectiv
cj = 2j + 1 xj , nu se pot afla nici pe o aceeasi diagonala avand directia
stanga-sus dreapta-jos:
xi xj 6= ci cj , i 6= j, i, j = 1, n 1,
sau, echivalent,
xi xj 6= 2i + 1 xi 2j 1 + xj , i 6= j, i, j = 1, n 1,
adica
xi xj 6= i j, i 6= j, i, j = 1, n 1.
Conditiile de continuare:
Daca avem solutia partiala (x1 , . . . , xk1 ), atunci xk verific
a conditiile de
continuare (este valid ) daca
xk xi 6= k i, i = 1, k 1.
Altfel spus, daca avem solutia partiala x = (x1 , . . . , xk1 ), atunci xk nu
verifica conditiile de continuare (nu este valid ) daca
i {1, 2, . . . , k 1} astfel ncat xk xi = k i.
Obtinem urmatorul algoritm Backtracking, descris n pseudocod, pentru
rezolvarea problemei.
Algoritmul 3.4.1.
83
NEBUNI1 (n) :
k 1;
x[1] 0;
ult 2;
// ult este valoarea final
a bk pentru xk
while k > 0 do
if x[k] < ult then
x[k] x[k] + 1;
if VALID1(x, k) then
if k = n 1 then
AFISARE(x);
else
k k + 1;
// preg
atim introducerea valorii init
iale ak s
i
// actualiz
am valoarea final
a bk pentru xk
n
if k then
2
x[k] 0;
ult 2k;
else
x[k] 2k n;
ult n;
else
k k 1;
// actualiz
am valoarea final
a bk pentru xk
n
if k then
2
ult 2k;
else
ult n;
// fals
// adev
arat
84
n+1
,
{(l, 2k l) | 1 l 2k 1}, daca 2 k
2
Dk =
n+1
< k n 1.
{(l, 2k l) | 2k n l n}, daca
2
n+1
,
Sk = {1, 2, . . . , 2k 1}, daca 2 k
2
n+1
85
ak = 1,
n+1
rk = 1,
k = 2,
,
2
bk = 2k 1,
ak = 2k n,
n+1
rk = 1,
+ 1, n 1.
k =
2
bk = n,
Conditiile interne:
Analog cazului 1) obtinem:
yi yj 6= i j, i 6= j, i, j = 2, n 1.
In plus,
y1 {1, n}.
Conditiile de continuare:
Daca avem solutia partiala (y1 , . . . , yk1 ), cu k 2, atunci yk verific
a
conditiile de continuare (este valid ) daca
yk yi 6= k i, i = 2, k 1.
Altfel spus, daca avem solutia partiala (y1 , . . . , yk1 ), cu k 2, atunci yk
nu verifica conditiile de continuare (nu este valid ) daca
i {2, . . . , k 1} astfel ncat yk yi = k i.
Obtinem urmatorul algoritm Backtracking, descris n pseudocod, pentru
rezolvarea problemei.
Algoritmul 3.4.2.
86
NEBUNI2 (n) :
// presupunem c
a n3
k 2;
y[2] 0;
ult 3;
// ult este valoarea final
a bk pentru yk
while k > 1 do
if y[k] < ult then
y[k] y[k] + 1;
if VALID2(y, k) then
if k = n 1 then
y[1] 1;
// primul nebun pe p
atr
a
telul (1, 1)
AFISARE(y);
y[1] n;
// primul nebun pe p
atr
a
telul (n, n)
AFISARE(y);
else
k k + 1;
// preg
atim introducerea valorii init
iale ak s
i
// actualiz
am valoarea final
a bk pentru yk
n+1
if k
then
2
y[k] 0;
ult 2k 1;
else
y[k] 2k n 1;
ult n;
else
k k 1;
// actualiz
am valoarea final
a bk pentru yk
n+1
if k
then
2
ult 2k 1;
else
ult n;
// fals
// adev
arat
87
Consideratii
Teorema 3.4.1. Pentru orice n 2 problema nebunilor are cel putin o
solutie.
Demonstratie. Avem din nou urmatoarele doua cazuri.
Cazul 1) Cei n 1 nebuni trebuie asezati pe patratele de culoare neagra.
Atunci o solutie este data de asezarea celor n 1 nebuni n patratelele de
coordonate (l, c) ce apartin multimii
n1
n1
(n, 2i) | 1 i
, daca n este impar,
(1, 2i) | 1 i
2
2
respectiv multimii
n
no n
no
(1, 2i) | 1 i
(n, 2i 1) | 2 i
, daca n este par.
2
2
88
3.5
3.5.1
1, daca n = 0,
x(x 1) . . . (x n + 1), daca n 1,
[x]n =
{z
}
|
n factori
1, daca n = 0,
n
x(x + 1) . . . (x + n 1), daca n 1.
[x] =
{z
}
|
n factori
3.5.2
89
Produs cartezian
ak = 1,
rk = 1,
k = 1, n.
bk = mk ,
Conform Observatiei 3.1.13, eliminam verificarea conditiilor de continuare.
PRODUS CARTEZIAN(n, m) :
k 1;
x[1] 0;
while k > 0 do
if x[k] < m[k] then
x[k] x[k] + 1;
if k = n then
AFISARE(x, n);
else
k k + 1;
x[k] 0;
else
k k 1;
90
3.5.3
Submultimi
91
B P(A)
{a, b, c}
{a, b}
{a, c}
{a}
{b, c}
{b}
{c}
3.5.4
92
Aranjamente cu repetitie
3.5.5
Aranjamente
93
Avem
n
C1 = (x1 , x2 , . . . , xn )|x1 {1, . . . , m},
x2 {1, . . . , m} \ {x1 },
x3 {1, . . . , m} \ {x1 , x2 },
...,
o
xn {1, . . . , m} \ {x1 , . . . , xn1 } ,
ak = 1,
rk = 1, k = 1, n.
bk = m,
Conditiile interne:
xi 6= xj , i 6= j, i, j = 1, n.
94
Conditiile de continuare:
Daca avem solutia partiala (x1 , . . . , xk1 ), atunci xk verific
a conditiile de
continuare daca
xk 6= xi , i = 1, k 1.
Altfel spus, daca avem solutia partiala x = (x1 , . . . , xk1 ), atunci xk nu
verifica conditiile de continuare daca
i {1, 2, . . . , k 1} astfel ncat xk = xi .
ARANJAMENTE1(m, n) :
k 1;
x[1] 0;
while k > 0 do
if x[k] < m then
x[k] x[k] + 1;
if VALID(x, k) then
if k = n then
AFISARE(x, n);
else
k k + 1;
x[k] 0;
else
k k 1;
VALID(x, k) :
for i = 1, k 1 do
if x[k] = x[i] then
returneaz
a 0;
returneaz
a 1;
// fals
// adev
arat
95
// dup
a revenire, se elimin
a
// x[k] din solut
ia part
ial
a
3.5.6
96
Permut
ari
PERMUTARI1(n)
:
k 1;
x[1] 0;
while k > 0 do
if x[k] < n then
x[k] x[k] + 1;
if VALID(x, k) then
if k = n then
AFISARE(x, n);
k k 1;
// fort
am revenirea, deoarece
// nu mai exist
a valori valide pentru x[n]
else
k k + 1;
x[k] 0;
else
k k 1;
97
// fals
// adev
arat
PERMUTARI2(n)
:
for i = 1, n do y[i] 0;
k 1;
x[1] 0;
while k > 0 do
if x[k] < n then
x[k] x[k] + 1;
if y[x[k]] = 0 then
if k = n then
AFISARE(x, n);
k k 1;
y[x[k]] 0;
else
y[x[k]] 1;
k k + 1;
x[k] 0;
else
k k 1;
y[x[k]] 0;
Functia de afisare este aceeasi ca n algoritmul anterior.
Observatia 3.5.6. Pentru generarea permutarilor unei multimi arbitrare A =
{a1 , a2 , . . . , an } nlocuim afisarea indicilor (x1 , . . . , xn ) cu afisarea elementelor
corespunzatoare (ax1 , . . . , axn ).
3.5.7
98
Combin
ari
99
ak = xk1 + 1,
rk = 1,
k = 1, n,
bk = m n + k,
100
considerand x0 = 0.
Prin alegerea multimilor S1 , S2 , . . . , Sn am eliminat verificarea conditiilor
de continuare.
COMBINARI(m,
n) :
k 1;
x[1] 0;
while k > 0 do
if x[k] < m n + k then
x[k] x[k] + 1;
if k = n then
AFISARE(x, n);
else
k k + 1;
x[k] x[k 1];
else
k k 1;
3.5.8
Combin
ari cu repetitie
101
ak = xk1 ,
rk = 1,
k = 1, n,
bk = m,
102
considerand x0 = 1.
Prin alegerea multimilor S1 , S2 , . . . , Sn am eliminat verificarea conditiilor
de continuare.
COMBINARI
CU REPETIT
IE(m, n) :
k 1;
x[1] 0;
while k > 0 do
if x[k] < m then
x[k] x[k] + 1;
if k = n then
AFISARE(x, n);
else
k k + 1;
x[k] x[k 1] 1;
else
k k 1;
3.5.9
Permut
ari cu repetitie
103
...
t1 !(n t1 )! t2 !(n t1 t2 )!
tm !(n t1 . . . tm )!
n!
=
t1 !t2 ! . . . tm !
(deoarece (n t1 . . . tm )! = 0! = 1).
Definitia 3.5.9. Cuvintele numarate n propozitia anterioara se numesc
permut
ari cu repetitie (anagrame)
de nluate cate t1 , t2 , . . . , tm . De
n
, se numeste tot permut
ari
asemenea si numarul lor, adica
t1 , t2 , . . . , tm
cu repetitie de n luate c
ate t1 , t2 , . . . , tm .
Observat
ia 3.5.10. Luand t1 = t2 = = tm = 1 obtinem n = m si
n
= n!, deci permutarile (fara repetitie) sunt un caz particu1, 1, . . . , 1
lar
permutarilor cu repetitie. Pe de alta parte, luand m = 2 obtinem
al
n!
n
=
, deci si combinarile (fara repetitie) sunt un caz particular
t1 , t2
t1 !t2 !
al permutarilor cu repetitie.
104
ak = 1,
rk = 1, k = 1, n.
bk = m,
Conditiile interne:
105
CU REPETIT
IE1(n, t, m) :
PERMUTARI
n 0;
for i = 1, m do n n + t[i];
k 1;
x[1] 0;
while k > 0 do
if x[k] < m then
x[k] x[k] + 1;
p t[x[k]];
if VALID(p, x, k) then
if k = n then
AFISARE(x, n);
k k 1;
// fort
am revenirea, deoarece
// nu mai exist
a valori valide pentru x[n]
else
k k + 1;
x[k] 0;
else
k k 1;
VALID(p, x, k) :
// p = t[x[k]]
q 0;
// q reprezint
a card ({i|i = 1, k 1, x[i] = x[k]})
if p = 0 then returneaz
a 0;
for i = 1, k 1 do
if x[i] = x[k] then
q q + 1;
if q p then returneaz
a 0;
returneaz
a 1;
106
PERMUTARI
CU REPETIT
IE2(n, t, m) :
n 0;
for i = 1, m do n n + t[i];
for i = 1, m do y[i] 0;
// init
ial, solut
ia part
ial
a este
// vectorul vid
k 1;
x[1] 0;
while k > 0 do
if x[k] < m then
x[k] x[k] + 1;
if y[x[k]] < t[x[k]] then
// x[k] verific
a condit
iile
// de continuare
if k = n then
AFISARE(x, n);
k k 1;
y[x[k]] y[x[k]] 1; // dup
a fort
area revenirii,
// se elimin
a x[k] din solut
ia part
ial
a
else
y[x[k]] y[x[k]] + 1;
// ^
nainte de avansare, se
// adaug
a x[k] la solut
ia part
ial
a
k k + 1;
x[k] 0;
else
k k 1;
y[x[k]] y[x[k]] 1;
// dup
a revenire, se elimin
a
// x[k] din solut
ia part
ial
a
Tema 4
Metoda Divide et Impera
4.1
n N cu n > n0 , m1 , . . . , ma N cu mi
P (m1 ), . . . , P (ma )
107
108
n
<n
b
109
COMBINA(S1 , S2 , S)
realizeaza combinarea rezultatelor S1 , S2 ale prelucrarii celor doua subsecvente vecine (p, m) si (m + 1, q), obtinandu-se rezultatul S al prelucrarii secventei (p, q).
Valoarea m este obtinuta apeland procedura
DESCOMPUNERE(p, q, m).
4.2
110
111
112
vI(T )
vI(T )
vE(T )
vI(T )
vI(T )\{x}
DT (v) + 2n.
vI(T )
113
si
vE(T )
Demonstratie. Consideram din nou ca nivelul pe care este reprezentata radacina arborelui este numerotat cu 0. Rezulta ca:
arborele are h(T ) nivele;
pe nivelele 0, 1, . . . , h(T ) 2 avem doar noduri interne, fiecare avand
cate doi descendenti;
pe penultimul nivel, h(T )1, putem avea si noduri externe, iar nodurile
interne de pe acest nivel au de asemenea cate doi descendenti;
114
(4.2.1)
vE(T )
(4.2.3)
1 n + 1 2h(T )1 2h(T )1 .
deci
= (n + 1)h(T ) + 2a n 1
= (n + 1)h(T ) + 2 n + 1 2h(T )1 n 1
= (n + 1)h(T ) + n + 1 2h(T )
(4.2.4)
115
Mai mult, egalitatea are loc daca si numai daca toate nodurile externe sunt
situate pe ultimul si, eventual, pe penultimul nivel.
Demonstratie. Notam
M = {T | T = arbore binar strict, card (I(T )) = n},
X
S(T ) =
DT (v), T M.
vE(T )
116
Avem
S(T ) S(T ) =
vE(T )
DT (v)
DT (v)
vE(T )
tn ,
daca n n0 ,
a
P
T (n) =
(4.2.5)
T (mi ) + f (n), daca n > n0 ,
i=1
unde:
pentru n n0 , tn reprezinta timpul de executie necesar rezolvarii directe a problemei, adica timpul de executie al procedurii PRELUCREAZA(n, S);
pentru n > n0 , f (n) reprezinta timpul total de executie necesar descompunerii problemei n subprobleme si combinarii solutiilor acestor subprobleme, adica suma timpilor de executie ai procedurilor DESCOMPUNERE(n, a, m) si COMBINA(s, a, S).
117
Adesea subproblemele P (m1 ), P (m2 ), . . . , P (ma ), obtinute la descompunerea problemei P (n), au dimensiuni egale
nj n k l n mo
m1 = m2 = = ma
,
,
(4.2.6)
b
b
sau, mai general, aproape egale.
m1 , m2 , . . . , ma
nj n k l n mo
,
,
b
b
(4.2.7)
unde
a1 = card
i = 1, a | mi =
j n ko
b
, a2 = card
n
l n mo
i = 1, a | mi =
,
b
a1 + a2 = a.
Observatia 4.2.5. Relatia de recurenta anterioara poate fi scrisa sub forma
T (n) = T (n/b) + + T (n/b) +f (n), n > n0 ,
{z
}
|
a termeni
jnk
lnm
unde, prin conventie, fiecare termen n/b reprezinta fie
, fie
.
b
b
Mai mult, prin abuz de notatia de nmultire, aceasta relatie este conventional rescrisa prescurtat sub forma
T (n) = aT (n/b) + f (n), n > n0 .
Urmatorul rezultat prezinta o metoda generala pentru rezolvarea acestei
relatii de recurenta.
Teorema 4.2.1 (Teorema Master). Fie T : N R o functie ce verific
a
relatia de recurenta
T (n) = aT (n/b) + f (n), n > n0
(4.2.8)
118
4.3
Modelarea problemei
Vom nota o mutare cu perechea (i, j), ceea ce semnifica faptul ca se muta un
disc de pe tija i pe tija j (i, j {1, 2, 3}).
Daca n = 1, solutia directa este mutarea (1, 2).
Daca n = 2, o solutie este formata din mutarile (1, 3), (1, 2), (3, 2).
119
120
// se afi
seaz
a mutarea (i, j)
// se afi
seaz
a mutarea (i, j)
1,
daca n = 1,
M(n 1) + 1 + M(n 1), daca n 2,
1,
daca n = 1,
2 M(n 1) + 1, daca n 2.
121
4.4
C
autarea binar
a
Problema c
aut
arii este urmatoarea:
Se considera un vector A = (a1 , a2 , . . . , an ), n 1, si o valoare x. Se cere
sa se determine daca x se afla printre componentele vectorului A.
O cautare se poate ncheia:
fie cu succes, caz n care se returneaza o pozitie n vector pe care se
afla valoarea cautata;
fie f
ar
a succes, caz n care se returneaza 1.
122
123
CAUTBIN(A, n, x) :
p 1; u n;
// (ap , . . . , au ) reprezint
a subsecvent
a curent
a
// la care se restr^
ange c
autarea
while p
u
do
p+u
;
m
2
if x = A[m] then
returneaz
a m;
else
if x < A[m] then
u m 1;
else
p m + 1;
returneaz
a 1;
Procedura trebuie apelata prin:
poz CAUTBIN(A, n, x).
Observatia 4.4.2. Pentru analiza algoritmului de cautare binara, presupunem
ca la fiecare iteratie avem o singura comparatie de chei, ntre valoarea cautata
x si un element ai al vectorului, n urma careia se poate decide ce relatie de
ordine exista ntre valorile comparate.
Prezentam cateva notiuni ajutatoare.
Definitia 4.4.1. Un arbore binar de c
autare (BST - Binary Search
Tree) este un arbore binar cu proprietatea ca orice nod intern are valoarea
(cheia) mai mare decat orice nod din subarborele sau stang si mai mica decat
orice nod din subarborele sau drept.
Observatia 4.4.3. Parcurgerea n INORDINE (ST, RAD, DR) a unui arbore
de cautare corespunde parcurgerii n ordine crescatoare a valorilor (cheilor)
nodurilor sale.
Observatia 4.4.4. Fie A un algoritm de cautare, bazat pe comparatii de chei,
a unei valori x ntr-un vector sortat cu n componente A = (a1 , a2 , . . . , an ),
a1 a2 an .
Presupunem ca algoritmul nu contine instructiuni redundante si este aplicabil pentru orice pozitionare posibila a valorii x n raport cu componentele
vectorului A, deci valoarea x este comparata exact cate o data cu fiecare
componemta ai , i = 1, n.
Atunci algoritmului A i se poate asocia un arbore binar de cautare T (A)
avand n noduri, etichetate cu numerele 1, 2, . . . , n, construit recursiv astfel:
124
125
Figura 4.4.1:
Observatia 4.4.6. Arborele binar extins de cautare asociat algoritmului cautarii binare ntr-un vector sortat cu n componente poate fi construit si direct
prin urmatorul procedeu recursiv:
a) daca n = 0, arborele este constituit din nodul 0 ;
b) altfel, daca n 1, atunci:
n+1
este nod r
ad
acin
a (nodul median este radacina);
2
subarborele st
ang este arborele
binar
corespunzator cautarii
n+1
binare ntr-un vector sortat cu
1 componente;
2
126
127
Figura 4.4.2:
Observatia 4.4.9. In cazul unei cautari fara succes, eticheta nodului extern n
care se ajunge, poate determina pozitia pe care ar trebui inserata n vector
valoarea cautata, astfel ncat vectorul sa ramana n continuare sortat.
Propozitia 4.4.1 (complexitatea algoritmilor de c
autare). Pentru orice
algoritm de cautare A, bazat pe comparatii de chei, a valorii x n vectorul
sortat A = (a1 , a2 , . . . , an ) avem:
1) numarul de comparatii de chei efectuate n cazul cel mai defavorabil
este mai mare sau egal cu
log2 (n + 1) ;
2) numarul mediu de comparatii de chei efectuate este mai mare sau egal
cu
n + 2 2 2log2 (n+1)
2n + 2
log2 (n + 1) +
.
2n + 1
2n + 1
128
2n + 1
n + 2 2 2log2 (n+1)
2n + 2
log2 (n + 1) +
.
=
2n + 1
2n + 1
129
(4.4.1)
130
3n + 4 4 2log2 n
2n + 2
log2 n +
.
2n + 1
2n + 1
n
Evident, log2 n 1 < log2 n log2 n, deci < 2log2 n n. Rezulta ca
2
T (n) =
log2 n
3n 2 log2 n
n + 4 + log2 n
< T (n) < log2 n +
,
2n + 1
2n + 1
deci
1
T (n)
n + 4 + log2 n
3n 2 log2 n
<
<1+
, n 2.
(2n + 1) log2 n
log2 n
(2n + 1) log2 n
4.5
4.5.1
131
Algoritmi de sortare
Problema sort
arii
Problema sort
arii este urmatoarea:
Se considera un vector A = (a1 , a2 , . . . , an ), n 1. Se cere sa se ordoneze
crescator (sau descrescator) elementele acestui vector.
Observatia 4.5.1. In practica, problema apare, n general, n ordonarea crescatoare (sau descrescatoare) a unei multimi finite de articole (nregistrari)
dupa un camp (sau mai multe) numit cheie de sortare.
Observatia 4.5.2. Fie A un algoritm de sortare, bazat pe comparatii de chei,
a unui vector A = (a1 , a2 , . . . , an ), n 1.
Presupunem ca algoritmul nu contine instructiuni redundante si este aplicabil pentru orice pozitionare posibila a componentelor vectorului A, adica
pentru orice permutare a acestora.
Atunci algoritmului A i se poate asocia un arbore binar T (A) n care
fiecare nod are o eticheta de forma i?j, construit recursiv astfel: daca prima
comparatie efectuata de algoritm este ntre elementele ai si aj ale vectorului,
atunci
radacina arborelui este etichetata cu i?j;
subarborele stang corespunde continuarii algoritmului n cazul ai aj ,
daca acest caz este posibil dupa prima comparatie (altfel este vid, adica
nu exista descendent stang);
subarborele drept corespunde continuarii algoritmului n cazul ai > aj ,
daca acest caz este posibil dupa prima comparatie (altfel este vid, adica
nu exista descendent drept).
Definitia 4.5.1. Arbore binar T (A) construit n observatia anterioara se
numeste arborele de sortare sau arborele de decizie al algoritmului
de sortare A.
132
Observatia 4.5.3. Deoarece algoritmul A este aplicabil pentru orice permutare a vectorului A = (a1 , a2 , . . . , an ) si nu contine instructiuni redundante, rezulta ca n arborele extins de sortare T (A) fiecare permutarea
a multimii de indici {1, 2, . . . , n} apare exact o data ca eticheta a unui nod
extern, deci acest arbore are n! noduri externe si, conform Propozitiei 4.2.1,
n! 1 noduri interne.
1
2log2 n!
log2 n! 1 + .
n!
n!
133
Nmed (n)
Cum log2 n! log2 n! < 1 + log2 n!, rezulta ca 2log2 n! < 2 n!, adica
2log2 n!
1
2log2 n! 2 n! 1, deci log2 n! + 1
log2 n! 1 + .
n!
n!
Corolarul 4.5.1. Fie A un algoritm de sortare, bazat pe comparatii de chei,
a unui vector cu n componente si fie T = T (A) arborele extins de sortare
asociat.
1) Algoritmul A este optim n raport cu timpul de executie n cazul cel mai
defavorabil daca arborele T are toate nodurile externe situate pe ultimul si,
eventual, pe penultimul nivel. Mai mult, n acest caz numarul de comparatii
de chei efectuate n cazul cel mai defavorabil, notat cu Ndef (n), verific
a egalitatea
Ndef (n) = log2 n! ;
2) Algoritmul A este optim n raport cu timpul mediu de executie daca
si numai daca arborele T are toate nodurile externe situate pe ultimul si,
eventual, pe penultimul nivel. Mai mult, n acest caz numarul mediu de
comparatii de chei efectuate, notat cu Nmed (n), verifica relatiile
Nmed (n) = log2 n! + 1
2log2 n!
1
log2 n! 1 + .
n!
n!
134
(4.5.1)
(4.5.2)
< 1 + ln 2,
< 1 + ln 3,
...
n ln n (n 1) ln(n 1) < 1 + ln n.
Prin adunare obtinem ca
n ln n < n 1 + ln n!, n 2,
de unde, utilizand formula log2 x = log2 e ln x, x > 0, rezulta prima
inegalitate din (4.5.2), valabila si pentru n = 1. A doua inegalitate din
(4.5.2) este o consecinta a inegalitatii evidente n! nn .
Lema 4.5.2. Avem
log2 n! n log2 n
(adica functiile log2 n! si n log2 n sunt asimptotic echivalente).
Demonstratie. Din (4.5.2) rezulta ca
1
(n 1) log2 e
log2 n!
1, n N ,
n log2 n
n log2 n
135
4.5.2
Problema interclas
arii este urmatoarea:
Se considera doi vectori
A = (a1 , a2 , . . . , am ), m 1,
B = (b1 , b2 , . . . , bn ), n 1,
ale caror componente sunt sortate (ordonate) crescator, adica
a1 a2 . . . am ,
b1 b2 . . . bn .
Se cere sa se construiasca un vector cu m + n componente
C = (c1 , c2 , . . . , cm+n ),
care sa contina toate componentele vectorilor A si B si care sa fie, de asemenea, sortat crescator, adica
c1 c2 . . . cm+n .
Definitia 4.5.3. Spunem ca elementele vectorului C se obtin prin interclasarea (intercalarea) elementelor vectorilor A si B.
Algoritmul 4.5.1 (Interclasarea a doi vectori).
Pentru parcurgerea componentelor celor trei vectori A, B si C vom
utiliza trei indici i, j si respectiv k.
Initial toti acesti trei indici au valoarea 1.
136
m+n
137
Propozitia 4.5.2 (complexitatea algoritmului de interclasare). Algoritmul de interclasare a doi vectori cu m si respectiv n componente are
complexitatea (m + n).
Demonstratie. Fie T (m, n) timpul de executie al algoritmului.
Vom numara numai operatiile de comparatie si de atribuire n care intervin elemente ale vectorilor. Celelalte operatii care se efectueaza au acelasi
ordin de crestere cu cele pe care le analizam.
Numarul de atribuiri n care intervin elemente ale vectorilor, numite si
deplas
ari, notat cu Nd (m, n), este egal cu numarul de componente ale
lui C, deci
Nd (m, n) = m + n.
(4.5.3)
Numarul de comparatii de chei (comparatii n care intervin elemente
ale vectorilor), notat cu Nc (m, n), este egal cu numarul de executii ale
ciclului while numerotat cu (1). Cu fiecare astfel de comparatie are loc
si o atribuire pentru o componenta a vectorului C, adica o deplasare.
La terminarea ciclului while numerotat cu (1) elementele unuia dintre
vectorii A sau B au fost depuse integral n C, iar n celalalt vector au
mai ramas r elemente nedepuse n C, care vor fi depuse n C dupa
ncheierea acestui ciclu. Rezulta ca
Nc (m, n) = m + n r.
Evident,
1 r max{m, n},
deci
min{m, n} Nc (m, n) m
n 1} .
| +{z
| {z }
n cazul
cel mai favorabil
(4.5.4)
n cazul
cel mai defavorabil
138
1 nX
Tmediu (m, n) =
((c1 + c2 ) (m + n) c1 r) +
m + n r=1
n
o
X
+
((c1 + c2 ) (m + n) c1 r)
r=1
m(m + 1) + n(n + 1)
= (c1 + c2 ) (m + n) c1
2(m + n)
mn
m+n1
+ c2 (m + n).
+
= c1
2
m+n
Observatia 4.5.5. Evident, orice algoritm care rezolva problema data necesita
cel putin m + n instructiuni de atribuire pentru completarea elementelor
vectorului C, deci conform propozitiei anterioare rezulta ca algoritmul de
interclasare este asimptotic-optim.
4.5.3
139
// sortarea secvent
ei (ap , . . . , aq )
140
>
1?3
(1,2,3)
>
(3,1,2)
2?3
2?3
>
(1,3,2)
>
(3,2,1)
1?3
(2,1,3)
Figura 4.5.1:
>
(2,3,1)
141
Teorema 4.5.2 (complexitatea algoritmului de sortare prin interclasare). Algoritmul de sortare prin interclasare a unui vector cu n componente are complexitatea (n log2 n).
Demonstratie. Fie T (n) timpul de executie al algoritmului de sortare prin
interclasare. Vom demonstra ca T (n) = (n log2 n) prin doua metode.
Metoda 1) Vom estima efectiv timpul de executie T (n). Ca si la analiza complexitatii algoritmului de interclasare a doi vectori (Propozitia 4.5.2),
vom numara numai operatiile de comparatie de chei (comparatii n care intervin elemente ale vectorului) si de deplasare (atribuiri n care intervin elemente ale vectorului). Celelalte operatii care se efectueaza au acelasi ordin
de crestere cu cele pe care le analizam.
Avem
T (n) = c1 Nc (n) + c2 Nd (n),
(4.5.5)
unde Nc (n) si Nd (n) reprezinta numarul de comparatii de chei, respectiv
numarul de deplasari efectuate de algoritm, iar c1 , c2 > 0 sunt constante ce
reprezinta costurile n timp ale executarii unei comparatii de chei si, respectiv, ale unei deplasari.
Conform descrierii recursive a algoritmului, rezulta ca numerele Nc (n) si
Nd (n) verifica, respectiv, relatiile de recurenta
(
0,
l n m j n k daca n = 1,
l n m
j n k
Nc (n) =
Nc
+ Nc
+ Nc
,
, daca n > 1,
2
2
2
2
(4.5.6)
(
0,
j n k
l n m
l n m j n k daca n = 1,
Nd (n) =
+ Nd
+ Nd
,
, daca n > 1,
Nd
2
2
2
2
(4.5.7)
l n m j n k
l n m j n k
unde N c
,
si N d
,
reprezinta numarul de comparatii
2
2
2
2
de chei, respectiv numarul de ldeplas
ari efectuate la interclasarea celor doi
nm jnk
si
).
vectori sortati (de dimensiuni
2
2
Conform demonstratiei Propozitiei 4.5.2, si anume relatiilor (4.5.3) si
(4.5.4), avem
l n m j n k l n m j n k
Nd
,
=
+
= n,
(4.5.8)
2
2
2
2
m
j
k
nj
k
j
k
o
l n
n
n
n
,
,
+ 1, . . . , n 1 .
(4.5.9)
Nc
2
2
2
2
Notand cu Nc+ (n) numarul de comparatii de chei n cazul cel mai defavorabil,
142
(4.5.10)
j n k
j n k
+ 1 Nc+
+ 1.
2
2
j n1,
k
2
daca n = 1,
+ 1, daca n > 1.
(4.5.11)
(4.5.12)
(4.5.13)
prin inductie.
Pentru n = 1 avem u(1) = 1 = log2 2.
Presupunem egalitatea adevarata pentru orice k {1, . . . , n 1} si o
demonstram pentru n (n 2). Intr-adev
j n k ar, folosind relatia de recurenta
avem
(4.5.12) si ipoteza de inductie pentru
2
j n k
j n k
l
m
u(n) = u
+ 1 = log2
+ 1 + 1.
2
2
143
deci
(4.5.14)
Astfel avem
Nc+ (n)
n
X
i=2
p1
X
log2 i =
j
2
X
p1
X
j=1
2
X
log2 i +
j=1 i=2j1 +1
j+
j=1 i=2j1 +1
p1
X
n
X
i=2p1 +1
p=
p1
X
j=1
n
X
log2 i
i=2p1 +1
= np 2p + 1,
144
deci
Nc+ (n)
n
X
i=2
(4.5.15)
(4.5.16)
+ Nc
+
, daca n > 1.
Nc
2
2
2
prin inductie.
Pentru n = 1 avem Nc (2) = 1 > 0 = Nc (1).
Presupunem inegalitatea adevarata pentru orice k {1, . . . , n 1} si o
demonstram pentru n (n 2). Intr-adev
l n m ar, folosind relatia de recurenta
(4.5.17), ipoteza de inductie pentru
cand n este par, respectiv pentru
2
jnk
jnk
n+1
cand n este impar, precum si inegalitatea evidenta
,
2
2
2
avem
n+1
n+1
n+1
Nc (n + 1) = Nc
+ Nc
+
2
2
2
j n k j n k
l n m
+ Nc
+
Nc
2
2
2
= Nc (n).
Demonstratia prin inductie este ncheiata.
145
r = log2 n,
(4.5.18)
Nc (n) Nc (2r ).
(4.5.19)
= 22 Nc (2r2 ) (r 2)2r3
= ...
= 2r Nc (2rr ) (r r)2rr1
Cum Nc (1) = 0 obtinem ca Nc (2r ) r 2r1 = 0, deci
Nc (2r ) = r 2r1 , r N.
(4.5.20)
Din (4.5.19), (4.5.20) si (4.5.18) rezulta ca n cazul cel mai favorabil numarul
de comparatii de chei verifica inegalitatile
Nc (n) log2 n 2log2 n1
1
n log2 n, n N .
2
(4.5.21)
(4.5.22)
146
(4.5.23)
147
148
INTERCLAS2(A, p, q, m) :
i p;
j m + 1;
k 1;
while (i m) and (j q) do
if A[i] A[j] then
B[k] A[i];
i i + 1;
else
B[k] A[j];
j j + 1;
k k + 1;
if j q then
lim j 1;
else
lim q m + i 1;
for j = m, i, 1 do
A[q m + j] A[j];
k 1;
for i = p, lim do
A[i] B[k];
k k + 1;
4.5.4
Sortarea rapid
a (quicksort)
149
n care
ai ak aj ,
(4.5.24)
pentru orice i si j cu p i k 1 si k + 1 j u.
Se obtin, astfel, doua secvente mai mici (numite partitii)
(ap , . . . , ak1 ) si (ak+1 , . . . , au ),
care pot fi prelucrate (sortate), n acelasi mod, independent una de alta.
Secventele de lungime 1 sau cele vide care rezulta n urma partitionarii nu
se mai prelucreaza.
Un element ak , care satisface relatia (4.5.24), se numeste pivot. El are
proprietatea ca a ajuns deja pe pozitia finala, n viitorul vectorul sortat,
deoarece
toate elementele din secventa (ap , . . . , ak1) sunt mai mici sau egale cu
el;
toate elementele din secventa (ak+1 , . . . , au ) sunt mai mari sau egale cu
el.
La final, spre deosebire de algoritmul de sortare prin interclasare, n care
la etapa de combinare se realiza interclasarea celor doua secvente sortate,
aici aceasta etapa este evitata deoarece, n urma prelucrarilor celor doua
secvente, rezulta deja toata secventa (ap , . . . , au ) sortata.
Exemplul 4.5.2.
ap au (interschimbare)
pp+1
u u
150
ap au
p p
u u1
151
// pasul de cre
stere a lui p
// pasul de cre
stere a lui u
// se interschimb
a (cu semn inversat)
// valorile pa
silor de cre
stere
(n2 ),
pentru timpul de executie n cazul cel mai defavorabil,
152
n(n 1)
, n N.
2
(4.5.27)
Demonstram ca
N(n) N + (n), n N
(4.5.28)
prin inductie.
Pentru n {0, 1} avem N(n) = N + (n) = 0.
Presupunem inegalitatea adevarata pentru orice i {0, 1, . . . , n 1} si
o demonstram pentru n (n 2). Intr-adevar, folosind relatia de recurenta
(4.5.25), ipoteza de inductie pentru k 1 si n k si relatia (4.5.27) avem
N(n) = N(k 1) + N(n k) + n 1
N + (k 1) + N + (n k) + n 1
(k 1)(k 2) (n k)(n k 1)
=
+
+n1
2
2
n(n 1)
(k 1)(n k)
=
2
n(n 1)
.
2
Mai mult, egalitatea are loc daca si numai daca k {1, n} (la fiecare
partitionare!).
Astfel Cazul 1) este cel mai defavorabil, avand numarul de comparatii
n(n 1)
N + (n) =
si, prin urmare, complexitatea (n2 ).
2
Cazul 2) Notam cu N (n) numarul de comparatii de chei efectuate de
algoritm n cazul n care la fiecare partitionare cele doua partitii obtinute
153
N (n) =
n1
2
0,
+ N
n1
2
N (n + 1) N (n) = N
n1
n1
+1 N
+ 1,
2
2
0,
daca n = 0,
n1
+ 1, daca n 1.
2
v(n) = log2 (n + 2) 1, n N,
prin inductie.
Pentru n = 0 avem v(0) = 0 = log2 2 1.
(4.5.30)
(4.5.31)
(4.5.32)
154
2
2
n+1
r 2 < log2
+ 1 r 1;
2
n+1
+1
= r 1,
log2
2
deci
v(n) = r 1 = log2 (n + 2) 1,
(4.5.33)
155
(4.5.34)
Demonstram ca
N(n) N (n), n N
(4.5.35)
prin inductie.
Pentru n {0, 1} avem N(n) = N (n) = 0.
Presupunem inegalitatea adevarata pentru orice i {0, 1, . . . , n 1} si
o demonstram pentru n (n 2). Intr-adevar, folosind relatiile de recurenta
(4.5.25) si (4.5.29) si ipoteza de inductie pentru k 1 si n k avem
n1
(k) = N (k 1) + N (n k) N
n1
2
n1
2
(
notand
n caz contrar,
k = n + 1 k obtinem (k) = (k ) si k
n1
1, 2, . . . ,
+ 1 ).
2
n1
Pentru k =
+ 1 avem (k) = 0, deci N(n) N (n) 0.
2
n1
Pentru k 1, 2, . . . ,
, conform (4.5.33) avem
2
156
(k) = N (k 1) + N (n k) N
=
k
X
i=1
log2 i k + 1 +
nk+1
X
i=1
n1
2
n1
2
log2 i n + k
+1
n1
2
X
n1
n1
log2 i +
log2 i +
2
2
i=1
i=1
n1
n1
+1
+1
k
nk+1
2
2
X
X
X
X
log2 i
log2 i
log2 i
log2 i
=
n1
2
+1
i=1
i=1
nk+1
X
i=1
i=1
+1
n1
2
X
log2 i
log2 i
+2
i= n1
2
i=k+1
+1k
+1k
n1
n1
2
2
X
X
n1
log2 i +
log2 (i + k)
+1
=
2
i=1
i=1
+1k
n1
2
X
n1
log2 i +
+1
log2 (i + k)
=
2
i=1
0.
Nmed (n) =
n
P
Nk (n)
k=1
157
0,
daca n {0, 1},
P
n
Nmed (n) =
(Nmed (k 1) + Nmed (n k) + n 1)
k=1
, daca n 2.
n
n
P
k=1
2
=
Nmed (k 1) +
n
P
k=1
n
P
k=1
Nmed (n k) + n(n 1)
n
Nmed (k 1) + n(n 1)
n
0,
daca n {0, 1},
P
n
2
Nmed (k 1) + n(n 1)
Nmed (n) =
k=1
, daca n 2.
n
n
X
k=1
(n 1)Nmed (n 1) = 2
n1
X
k=1
Nmed (k 1) + n2 n,
158
(4.5.37)
1 1
1
+ + + si
2 3
n
1
1 1
+ ++
2 3
n = lim an = lim an+1 an
lim
n bn+1 bn
n bn
n
ln n
1
1
n
1
n+1
n =
= lim
= 1.
= lim
n n + 1
n ln(n + 1) ln n
ln e
1
ln 1 +
n
1+
Deducem ca
Nmed (n)
ln 2 Nmed (n)
lim
= lim
n n log2 n
n
n ln n
1 1
1
1
+
+
+
+
2(n + 1)
2 3
n 4
= ln 2 lim
n
n
ln n
ln n
= 2 ln 2,
(4.5.38)
159
160
// se determin
a pozit
ia median
a
// a secvent
ei de sortat
med A[k];
// se ret
ine elementul de pe pozit
ia median
a
min p;
max u;
repeat
while A[min] < med do
min min + 1
while A[max] > med do
max max 1
if min max then
A[min] A[max]
min min + 1;
max max 1;
while min max;
if p < max then
QUICKSORT2(A, p, max);
if u > min then
QUICKSORT2(A, min, u);
4.6
O problem
a de acoperire
161
n2 1
Consideram ca piesele sunt numerotate cu 1, 2, . . . ,
si ca asezarea
3
piesei numarul i consta n completarea elementelor corespunz
ma
atoare din
n2 1
.
tricea S cu numarul i al piesei, pentru fiecare valoare i 1, 2, . . . ,
3
Pentru rezolvarea problemei utilizam urmatoarea strategie Divide et Impera:
Se mparte suprafata patrata n patru patrate egale, formandu-se patru
suprafete patrate cu lungimea laturii 2k1 .
Una dintre cele patru suprafete are deja un patrat unitar acoperit.
Acoperim cu o placa trei patrate unitare din centrul suprafetei mari astfel ncat sa acoperim cate un patrat unitar si din celelalte trei suprafete.
Un exemplu n acest sens este redat n Figura 4.6.1.
Figura 4.6.1:
162
Algoritmul 4.6.1.
ACOPERIRE(S, i, j, n, ip, jp) :
// S=matricea ce va fi completat
a cu numerele pl
acilor
// (i, j)=colt
ul st^
anga sus
// n=lungimea laturii
// (ip, jp) = coordonatele p
atratului unitar acoperit
if (n > 1) then
p p + 1;
// num
arul pl
acii
m n/2;
// noua dimensiune a laturii
// Coordonatele st^
anga sus ale celor 4 p
atrate:
i1 i; j1 j;
i2 i; j2 j + m;
i3 i + m; j3 j;
i4 i + m; j4 j + m;
// Coordonatele p
atratelor unitare ce vor fi acoperite
// ^
n cele 4 p
atrate:
ip1 ip; jp1 jp;
ip2 ip; jp2 jp;
ip3 ip; jp3 jp;
ip4 ip; jp4 jp;
if (i3 ip) then
ip1 i1 + m 1; jp1 j1 + m 1;
ip2 i2 + m 1; jp2 j2;
S[ip1][jp1] p; S[ip2][jp2] p;
else
ip3 i3; jp3 j3 + m 1;
ip4 i4; jp4 j4;
S[ip3][jp3] p; S[ip4][jp4] p;
if (j2 jp) then
ip1 i1 + m 1; jp1 j1 + m 1;
ip3 i3; jp3 j3 + m 1;
S[ip1][jp1] p; S[ip3][jp3] p;
else
ip2 i2 + m 1; jp2 j2;
ip4 i4; jp4 j4;
S[ip2][jp2] p; S[ip4][jp4] p;
ACOPERIRE(S, i1, j1, m, ip1, jp1);
ACOPERIRE(S, i2, j2, m, ip2, jp2);
ACOPERIRE(S, i3, j3, m, ip3, jp3);
ACOPERIRE(S, i4, j4, m, ip4, jp4);
163
Tema 5
Metoda program
arii dinamice
5.1
164
TEMA 5. METODA PROGRAMARII
DINAMICE
165
Deci este de preferat ca relatiile de recurenta sa fie rezolvate prin implementari nerecursive, utilizand strategia bottom-up, cu memorarea temporara
a solutiilor optime ale subproblemelor.
Prezentam o schema generala de lucru:
Problema data se descompune n subprobleme de acelasi tip, dar de
dimensiuni mai mici.
Se alege o structura de date n care se memoreaza solutiile optime ale
problemei si subproblemelor.
Se determina relatia de recurenta ce caracterizeaza solutia optima.
Se rezolva relatia de recurenta prin strategia bottom-up.
Observatia 5.1.1. Presupunem ca solutiile optime ale subproblemelor sunt
memorate ntr-un tablou
S = (S[i1 , . . . , ir ])(i1 ,...,ir )I1 Ir .
a) Daca relatia de recurenta ce caracterizeaza solutia optima exprima
elementul S[i1 , . . . , ir ] n functie de elemente urmatoare
S[j1 , . . . , jr ], (j1 , . . . , jr ) (i1 , . . . , ir )
(conform ordinii lexicografice), atunci calculul acestor elemente se face n
ordinea inversa, descrescatoare, a indicilor (i1 , . . . , ir ). Aceasta abordare este
denumita si programare dinamica n varianta napoi.
b) Daca relatia de recurenta ce caracterizeaza solutia optima exprima
elementul S[i1 , . . . , ir ] n functie de elemente anterioare
S[j1 , . . . , jr ], (j1 , . . . , jr ) (i1 , . . . , ir )
(conform ordinii lexicografice), atunci calculul acestor elemente se face n
ordinea directa, crescatoare, a indicilor (i1 , . . . , ir ). Aceasta abordare este
denumita si programare dinamica n varianta nainte.
5.2
TEMA 5. METODA PROGRAMARII
DINAMICE
166
TEMA 5. METODA PROGRAMARII
DINAMICE
167
construit astfel:
t1 = min {i | L[i] = k},
i=1,n
TEMA 5. METODA PROGRAMARII
DINAMICE
168
SUBSIRMAX1(A, n) :
L[n] 1;
for i = n 1, 1, 1 do
L[i] 1;
P [i] 1;
for j = i + 1, n do
if (aj ai ) and (1 + L[j] > L[i]) then
L[i] 1 + L[j];
P [i] j;
k L[1];
t1 1;
for i = 2, n do
if (L[i] > k) then
k L[i];
t1 i;
for j = 2, k do
tj P [tj1];
for j = 1, k do
afiseaz
a atj ;
Exemplul 5.2.2. La aplicarea algoritmului anterior pentru sirul din Exemplul
5.2.1 avem n = 10,
L[10] = 1;
L[9] = 1,
L[8] = 2,
L[7] = 3,
L[6] = 1,
L[5] = 3,
L[4] = 2,
L[3] = 4,
L[2] = 1,
L[1] = 2,
P [9] = 1;
P [8] = 9;
P [7] = 8;
P [6] = 1;
P [5] = 8;
P [4] = 6;
P [3] = 5;
P [2] = 1;
P [1] = 2,
TEMA 5. METODA PROGRAMARII
DINAMICE
169
adica subsirul
2, 4, 4, 9.
Observatia 5.2.1. Instructiunea
if(aj ai ) and (1 + L[j] > L[i])
construit astfel:
t1 {i = 1, n | L[i] = k},
tj P [tj1], j {2, . . . , k}.
Pentru generarea tuturor acestor vectori (t1 , t2 , . . . , tk ) se poate utiliza metoda
Backtracking.
TEMA 5. METODA PROGRAMARII
DINAMICE
170
P [9] = ;
P [8] = {9, 10};
P [7] = {8};
P [6] = ;
P [5] = {8};
P [4] = {6, 9, 10};
P [3] = {5, 7};
P [2] = ;
P [1] = {2, 6},
deci lungimea maxima a unui subsir crescator este k = 4 iar orice subsir
crescator de lungime maxima este dat de indicii
t1 {3}, t2 P [t1 ], t3 P [t2 ], t4 P [t3 ].
Obtinem ca subsirurile crescatoare de lungime maxima sunt
(a3 = 2, a5 = 4, a8 = 4, a9 = 9), (a3 = 2, a5 = 4, a8 = 4, a10 = 8),
(a3 = 2, a7 = 3, a8 = 4, a9 = 9), (a3 = 2, a7 = 3, a8 = 4, a10 = 8),
deci avem 4 solutii (subsiruri crescatoare de lungime maxima).
Metoda 2) Utilizam programarea dinamica, varianta nainte. Consideram
subproblemele constand n determinarea a cate unui subsir crescator de
lungime maxima care se ncheie cu elementul ai , pentru orice i {1, 2, . . . , n}.
Pentru memorarea solutiile subproblemelor utilizam din nou doi vectori
L = (L[1], . . . , L[n]) si P = (P [2], . . . , P [n]) avand acum semnificatia
L[i] = lungimea maxima a unui subsir crescator care se ncheie cu
elementul ai ,
P [i] = indicele primului element care este predecesor al lui ai ntr-un
subsir crescator de lungime maxima care se ncheie cu ai , daca
exista un astfel de indice,
P [i] = 1, daca nu exista un astfel de indice,
pentru orice i {1, 2, . . . , n}.
Evident,
L[1] = 1,
TEMA 5. METODA PROGRAMARII
DINAMICE
171
construit astfel:
tk = min {i | L[i] = k},
i=1,n
tj = P [tj+1], j {k 1, . . . , 1}.
Obtinem urmatorul algoritm de programare dinamica n varianta nainte,
descris n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.2.2.
TEMA 5. METODA PROGRAMARII
DINAMICE
172
SUBSIRMAX2(A, n) :
L[1] 1;
for i = 2, n do
L[i] 1;
P [i] 1;
for j = 1, i 1 do
if (aj ai ) and (1 + L[j] > L[i]) then
L[i] 1 + L[j];
P [i] j;
k L[1];
m 1;
for i = 2, n do
if (L[i] > k) then
k L[i];
m i;
// k = max{i = 1, n | L[i]}
// m = min{i = 1, n | L[i] = k}
tk m;
for j = k 1, 1, 1 do
tj P [tj+1];
for j = 1, k do
afiseaz
a atj ;
P [2] = 1;
P [3] = 1;
P [4] = 3;
P [5] = 3;
P [6] = 4;
P [7] = 3;
P [8] = 5;
P [9] = 8;
P [10] = 8,
TEMA 5. METODA PROGRAMARII
DINAMICE
173
iar un subsir crescator de lungime maxima este at1 at2 atk dat de
indicii
t4 = 9, t3 = P [t4 ] = 8, t2 = P [t3 ] = 5, t1 = P [t2 ] = 3,
adica subsirul
2, 4, 4, 9.
Observatia 5.2.3. Analog algoritmului de la Metoda 1, si algoritmul anterior
are complexitatea (n2 ).
Observatia 5.2.4. Printr-un procedeu similar celui descris n Observatia 5.2.2,
si algoritmul anterior poate fi adaptat pentru determinarea tuturor subsirurilor crescatoare de lungime maxima.
5.3
40 30 10 35 20 25
45 30 40 30 40 45
20 25 50 50 20 10
A=
10
15
20
35
15
30
40 50 60 55 65 80
40 20
15
20
10
10
TEMA 5. METODA PROGRAMARII
DINAMICE
174
Pentru aceeasi matrice, un drum de suma minima este format din elementele ncadrate n patrate, avand suma 135.
Modelarea problemei
a) Consideram problema drumului de suma maxima.
Metoda 1) Utilizam programarea dinamica, varianta napoi. Consideram
subproblemele constand n determinarea a cate unui drum de suma maxima
care ncepe cu elementul aij (si se ncheie cu un element de pe ultima linie),
pentru orice i {1, 2, . . . , m} si orice j {1, 2, . . . , n}.
Pentru memorarea solutiile subproblemelor utilizam doua matrice S =
(S[i, j]) i = 1, m si P = (P [i, j]) i = 1, m 1 avand semnificatia
j = 1, n
j = 1, n
0,
daca exista un drum de suma maxima de la aij la ultima
pe ai+1,j1,
TEMA 5. METODA PROGRAMARII
DINAMICE
175
construit astfel:
t1 = min {j | S[1, j] = M},
j=1,n
TEMA 5. METODA PROGRAMARII
DINAMICE
176
DRUMMAX1(A, m, n) :
for j = 1, n do S[m, j] amj ;
for i = m 1, 1, 1 do
P [i, 1] 0;
if S[i + 1, 2] > S[i + 1, 1] then P [i, 1] 1;
S[i, 1] ai1 + S[i + 1, 1 + P [i, 1]];
for j = 2, n 1 do
P [i, j] 1;
if S[i + 1, j] > S[i + 1, j 1] then P [i, j] 0;
if S[i + 1, j + 1] > S[i + 1, j + P [i, j]] then P [i, j] 1;
S[i, j] aij + S[i + 1, j + P [i, j]];
P [i, n] 1;
if S[i + 1, n] > S[i + 1, n 1] then P [i, n] 0;
S[i, n] ain + S[i + 1, n + P [i, n]];
M S[1, 1];
t1 1;
for j = 2, n do
if S[1, j] > M then
M S[1, j];
t1 j;
for i = 2, m do
ti ti1 + P [i 1, ti1 ];
afiseaz
a M;
for i = 1, m do
afiseaz
a aiti ;
// (*)
S=
125 105 100 115 105 110 ,
80 90 80 75 85 90
40 20 15 20 10 10
0 1
0 1 0 1
1 1
0 1 1 1
.
0
1
1
0
1
0
P =
1 0 1 1
1
0
0 1 1 0 1 1
TEMA 5. METODA PROGRAMARII
DINAMICE
177
Avem
t1 = min {j | S[1, j] = M} = 4,
j=1,6
t2
t3
t4
t5
t6
= t1 + P [1, t1 ] = 4 + P [1, 4] = 4 1 = 3,
= t2 + P [2, t2 ] = 3 + P [2, 3] = 3 + 0 = 3,
= t3 + P [3, t3 ] = 3 + P [3, 3] = 3 + 1 = 4,
= t4 + P [4, t4 ] = 4 + P [4, 4] = 4 + 1 = 5,
= t5 + P [5, t5 ] = 5 + P [5, 5] = 5 1 = 4,
TEMA 5. METODA PROGRAMARII
DINAMICE
178
construit astfel:
t1 {j = 1, n | S[1, j] = M},
ti {ti1 + k | k P [i 1, ti1 ]}, i {2, . . . , m}.
Pentru generarea tuturor acestor vectori (t1 , t2 , . . . , tm ) se poate utiliza metoda
Backtracking.
De exemplu, pentru matricea A din Exemplul 5.3.1 avem
S=
125 105 100 115 105 110 ,
80 90 80 75 85 90
40 20 15 20 10 10
{0, 1} {1}
{0}
{1, 1} {0}
{1}
{1}
{1}
{0, 1} {1, 0} {1} {1}
.
{0}
{1}
{1}
{0}
{1}
{0}
P =
{1}
{0}
{1}
{1}
{1}
{0}
{0} {1} {1, 1}
{0}
{1} {1, 0}
TEMA 5. METODA PROGRAMARII
DINAMICE
179
t1 {j = 1, 6 | S[1, j] = M} = {4},
t2 {4 + k | k P [1, 4]} = {3, 5},
pentru t2 = 3 : t3 {3 + k | k P [2, 3]} = {3, 4},
pentru t2 = 5 : t3 {5 + k | k P [2, 5]} = {4},
pentru t3 = 3 : t4 {3 + k | k P [3, 3]} = {4},
pentru t3 = 4 : t4 {4 + k | k P [3, 4]} = {4},
t5 {4 + k | k P [4, 4]} = {5},
t6 {5 + k | k P [5, 5]} = {4},
deci drumurile de suma maxima sunt
(a14 = 35, a23 = 40, a33 = 50, a44 = 30, a55 = 65, a64 = 20),
(a14 = 35, a23 = 40, a34 = 50, a44 = 30, a55 = 65, a64 = 20),
(a14 = 35, a25 = 40, a34 = 50, a44 = 30, a55 = 65, a64 = 20),
deci avem 3 solutii (drumuri de suma maxima).
Metoda 2) Utilizam programarea dinamica, varianta nainte. Consideram
subproblemele constand n determinarea a cate unui drum de suma maxima
care se ncheie cu elementul aij (si se ncepe cu un element de pe prima linie),
pentru orice i {1, 2, . . . , m} si orice j {1, 2, . . . , n}.
Pentru memorarea solutiile subproblemelor utilizam din nou doua matrice
S = (S[i, j]) i = 1, m si P = (P [i, j]) i = 1, m 1 avand acum semnificatia
j = 1, n
j = 1, n
TEMA 5. METODA PROGRAMARII
DINAMICE
180
Evident,
S[1, j] = a1j , j {1, . . . , n}
si pentru orice i {2, . . . , m} avem
S[i, 1] = ai1 + max{S[i 1, 1], S[i 1, 2]},
(
0, daca S[i 1, 1] S[i 1, 2],
P [i 1, 1] =
1, daca S[i 1, 1] < S[i 1, 2],
S[i, j] = aij + max{S[i 1, j 1], S[i 1, j], S[i 1, j + 1]},
j {2, . . . , n 1}
TEMA 5. METODA PROGRAMARII
DINAMICE
181
construit astfel:
tm = min {j | S[m, j] = M},
j=1,n
// (*)
TEMA 5. METODA PROGRAMARII
DINAMICE
182
S=
P =
40
85
105
145
185
235
30
70
110
140
195
235
10
75
125
135
215
230
35 20 25
65 75 70
125 95 85
155 140 115
210 220 220
240 230 230
0
1 1 0 1 0
0
1
0
1 0 1
1 1 0
1 1 1
.
0
1 1 0 1 1
1 1 0 1 0 1
Avem
t6 = min {j | S[6, j] = M} = 4,
j=1,6
t5
t4
t3
t2
t1
= t6 P [5, t6 ] = 4 P [5, 4] = 4 + 1 = 5,
= t5 P [4, t5 ] = 5 P [4, 5] = 5 1 = 4,
= t4 P [3, t4 ] = 4 P [3, 4] = 4 1 = 3,
= t3 P [2, t3 ] = 3 P [2, 3] = 3 0 = 3,
= t2 P [1, t2 ] = 3 P [1, 3] = 3 + 1 = 4,
TEMA 5. METODA PROGRAMARII
DINAMICE
183
for i = m, 2, 1 do
if (ti > 1) and (S[i 1, ti 1] = S[i, ti ] aiti ) then
ti1 ti 1;
// cobor^
are de forma
else
if S[i 1, ti ] = S[i, ti ] aiti then
ti1 ti ;
// cobor^
are de forma
else
ti1 ti + 1;
// cobor^
are de forma
Observatia 5.3.6. Analog Algoritmului 5.3.1, si Algoritmul 5.3.2 poate fi
adaptat pentru determinarea tuturor drumurilor de suma maxima.
j = 1, n
0,
daca exista un drum de suma minima de la aij la ultima
pe ai+1,j1 ,
1,
daca exista un drum de suma minima de la aij la ultima
TEMA 5. METODA PROGRAMARII
DINAMICE
184
construit astfel:
t1 = min {j | S[1, j] = M},
j=1,n
TEMA 5. METODA PROGRAMARII
DINAMICE
185
// (*)
S=
95 75 75 95 80 95 ,
60 65 75 65 75 90
40 20 15 20 10 10
TEMA 5. METODA PROGRAMARII
DINAMICE
P =
1 0 1 0 1 1
0 1 1 1
1
0
1 0 1 1 0 1
0 1 1 0 1 1
1 1
0
1
0 1
186
Avem
t1 = min {j | S[1, j] = M} = 3,
j=1,6
t2
t3
t4
t5
t6
= t1 + P [1, t1 ] = 3 + P [1, 3] = 3 1 = 2,
= t2 + P [2, t2 ] = 2 + P [2, 2] = 2 1 = 1,
= t3 + P [3, t3 ] = 1 + P [3, 1] = 1 + 1 = 2,
= t4 + P [4, t4 ] = 2 + P [4, 2] = 2 1 = 1,
= t5 + P [5, t5 ] = 1 + P [5, 1] = 1 + 1 = 2,
TEMA 5. METODA PROGRAMARII
DINAMICE
187
j = 1, n
0,
daca exista un drum de suma minima de la prima
1,
daca exista un drum de suma minima de la prima
TEMA 5. METODA PROGRAMARII
DINAMICE
188
construit astfel:
tm = min {j | S[m, j] = M},
j=1,n
TEMA 5. METODA PROGRAMARII
DINAMICE
189
DRUMMIN2(A, m, n) :
for j = 1, n do S[1, j] a1j ;
for i = 1, m 1 do
P [i, 1] 0;
if S[i, 2] < S[i, 1] then P [i, 1] 1;
S[i + 1, 1] ai+1,1 + S[i, 1 P [i, 1]];
for j = 2, n 1 do
P [i, j] 1;
if S[i, j] < S[i, j 1] then P [i, j] 0;
if S[i, j + 1] < S[i, j P [i, j]] then P [i, j] 1;
S[i + 1, j] ai+1,j + S[i, j P [i, j]];
P [i, n] 1;
if S[i, n] < S[i, n 1] then P [i, n] 0;
S[i + 1, n] ai+1,n + S[i, n P [i, n]];
M S[m, 1];
tm 1;
for j = 2, n do
if S[m, j] < M then
M S[m, j];
tm j;
for i = m 1, 1, 1 do
ti ti+1 P [i, ti+1 ];
afiseaz
a M;
for i = 1, m do
afiseaz
a aiti ;
// (*)
40 30 10 35 20 25
75 40 50 40 60 65
60 65 90 90 60 70
S=
95 75 75 90 75 80 ,
1 1 0 1 0 1
1 0 1 0 1 1
.
0
1
1
1
0
1
P =
1 0 1 1 0 1
0 1 1 0 1 1
TEMA 5. METODA PROGRAMARII
DINAMICE
190
Avem
t6 = min {j | S[6, j] = M} = 2,
j=1,6
t5
t4
t3
t2
t1
= t6 P [5, t6 ] = 2 P [5, 2] = 2 1 = 1,
= t5 P [4, t5 ] = 1 P [4, 1] = 1 + 1 = 2,
= t4 P [3, t4 ] = 2 P [3, 2] = 2 1 = 1,
= t3 P [2, t3 ] = 1 P [2, 1] = 1 + 1 = 2,
= t2 P [1, t2 ] = 2 P [1, 2] = 2 + 1 = 3,