Sunteți pe pagina 1din 167

PROIECTAREA ALGORITMILOR

Conf. univ. dr. COSTEL BĂLCĂU

2017
Tematica

1 Elemente de complexitatea algoritmilor s, i teoria grafurilor 7


1.1 Notat, ii asimptotice . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Parcurgerea grafurilor. Aplicat, ii . . . . . . . . . . . . . . . . . 12

2 Metoda Greedy 22
2.1 Descrierea metodei. Algoritmi generali . . . . . . . . . . . . . 22
2.2 Aplicat, ii ale Inegalităt, ii rearanjamentelor . . . . . . . . . . . . 25
2.2.1 Inegalitatea rearanjamentelor . . . . . . . . . . . . . . 25
2.2.2 Produs scalar maxim/minim . . . . . . . . . . . . . . . 27
2.2.3 Memorarea optimă a textelor pe benzi . . . . . . . . . 31
2.3 Problema rucsacului, varianta continuă . . . . . . . . . . . . . 33
2.4 Problema planificării spectacolelor . . . . . . . . . . . . . . . . 40
2.5 Arbori part, iali de cost minim . . . . . . . . . . . . . . . . . . 47
2.6 Distant, e s, i drumuri minime. Algoritmul lui Dijkstra . . . . . . 53
2.7 Fluxuri maxime ı̂n ret, ele . . . . . . . . . . . . . . . . . . . . . 62

3 Metoda Backtracking 85
3.1 Descrierea metodei. Algoritmi generali . . . . . . . . . . . . . 85
3.2 Colorarea grafurilor . . . . . . . . . . . . . . . . . . . . . . . . 93
3.3 Problema celor n dame pe tabla de s, ah . . . . . . . . . . . . . 96
3.4 Problema nebunilor pe tabla de s, ah . . . . . . . . . . . . . . . 100
3.5 Generarea obiectelor combinatoriale . . . . . . . . . . . . . . . 109
3.5.1 Preliminarii . . . . . . . . . . . . . . . . . . . . . . . . 109
3.5.2 Produs cartezian . . . . . . . . . . . . . . . . . . . . . 110
3.5.3 Submult, imi . . . . . . . . . . . . . . . . . . . . . . . . 111
3.5.4 Aranjamente cu repetit, ie . . . . . . . . . . . . . . . . . 113
3.5.5 Aranjamente . . . . . . . . . . . . . . . . . . . . . . . 114
3.5.6 Permutări . . . . . . . . . . . . . . . . . . . . . . . . . 117
3.5.7 Combinări . . . . . . . . . . . . . . . . . . . . . . . . . 119
3.5.8 Combinări cu repetit, ie . . . . . . . . . . . . . . . . . . 122
3.5.9 Permutări cu repetit, ie . . . . . . . . . . . . . . . . . . 124

1
TEMATICA 2

4 Metoda Divide et Impera 129


4.1 Descrierea metodei. Algoritmi generali . . . . . . . . . . . . . 129
4.2 Problema turnurilor din Hanoi . . . . . . . . . . . . . . . . . . 132
4.3 O problemă de acoperire . . . . . . . . . . . . . . . . . . . . . 135

5 Metoda programării dinamice 138


5.1 Descrierea metodei. Algoritmi generali . . . . . . . . . . . . . 138
5.2 Problema subs, irului crescător de lungime maximă . . . . . . . 139
5.3 Problema drumului de sumă maximă/minimă ı̂ntr-o matrice . 147

6 Metoda Branch and Bound 165

7 Algoritmi euristici 166


Evaluare

• Activitate laborator: 30% (Programe s, i probleme din Temele de labo-


rator)

• Teme de casă: 20% (Programe s, i probleme suplimentare)

• Examen final: 50% (Probă scrisă: teorie, algoritmi -cu implementare-


s, i probleme)

3
Bibliografie

[1] A.V. Aho, J.E. Hopcroft, J.D. Ullman, Data Structures and Algorithms, Addison-
Wesley, Massachusetts, 2009.

[2] Gh. Barbu, V. Păun, Programarea ı̂n limbajul C/C++, Editura Matrix Rom,
Bucures, ti, 2011.

[3] Gh. Barbu, V. Păun, Calculatoare personale s, i programare ı̂n C/C++, Editura Di-
dactică s, i Pedagogică, Bucures, ti, 2005.

[4] Gh. Barbu, I. Văduva, M. Bolos, teanu, Bazele informaticii, Editura Tehnică,
Bucures, ti, 1997.

[5] C. Bălcău, Combinatorică s, i teoria grafurilor, Editura Universităt, ii din Pites, ti,
Pites, ti, 2007.

[6] O. Bâscă, L. Livovschi, Algoritmi euristici, Editura Universităt, ii din Bucures, ti,
Bucures, ti, 2003.

[7] E. Cerchez, M. S, erban, Programarea ı̂n limbajul C/C++ pentru liceu. Vol. 2: Metode
s, i tehnici de programare, Ed. Polirom, Ias, i, 2005.

[8] E. Ciurea, L. Ciupală, Algoritmi. Introducere ı̂n algoritmica fluxurilor ı̂n ret, ele, Ed-
itura Matrix Rom, Bucures, ti, 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ă ı̂n optimizarea combinatorie, Editura Universităt, ii ”Al.
I. Cuza”, Ias, i, 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.

4
5

[15] H. Georgescu, Tehnici de programare, Editura Universităt, ii din Bucures, ti, Bucures, ti,
2005.

[16] C.A. Giumale, Introducere ı̂n analiza algoritmilor. Teorie s, i aplicat, ii, Ed. Polirom,
Ias, i, 2004.

[17] M. Goodrich, R. Tamassia, Algorithm Design. Foundatiolis, Analysis and Internet


Examples, Wiley, New Delhi, 2011.

[18] F.V. Jensen, T.D. Nielsen, Bayesian Networks and Decision Graphs, Springer, New
York, 2007.

[19] D. Jungnickel, Graphs, Networks and Algorithms, Springer, Heidelberg, 2013.

[20] D.E. Knuth, The Art Of Computer Programming. Vol. 4A: Combinatorial Algo-
rithms, Addison-Wesley, Massachusetts, 2011.

[21] B. Korte, J. Vygen, Combinatorial Optimization. Theory and Algorithms, Springer,


Heidelberg, 2012.

[22] R. Lafore, Data Structures and Algorithms in Java, Sams Publishing, Indianapolis,
2002.

[23] A. Levitin, Introduction to The Design and Analysis of Algorithms, Pearson, Boston,
2012.

[24] L. Livovschi, H. Georgescu, Sinteza s, i analiza algoritmilor, Editura S, tiint, ifică s, i


Enciclopedică, Bucures, ti, 1986.

[25] D. Logofătu, Algoritmi fundamentali ı̂n C++: Aplict, ii, Ed. Polirom, Ias, i, 2007.

[26] D. Lucanu, M. Craus, Proiectarea algoritmilor, Ed. Polirom, Ias, i, 2008.

[27] D.R. Popescu, Combinatorică s, i teoria grafurilor, Societatea de S, tiint, e Matematice


din România, Bucures, ti, 2005.

[28] N. Popescu, Data structures and algorithms using Java, Editura Politehnica Press,
Bucures, ti, 2008.

[29] V. Preda, C. Bălcău, Entropy optimization with applications, Editura Academiei


Române, Bucures, ti, 2010.

[30] R. Sedgewick, P. Flajolet, An Introduction to the Analysis of Algorithms, Addison-


Wesley, New Jersey, 2013.

[31] R. Sedgewick, K. Wayne, Algorithms, Addison-Wesley, Massachusetts, 2011.

[32] R. Stephens, Essential Algorithms: A Practical Approach to Computer Algorithms,


Wiley, Indianopolis, 2013.

[33] S, . Tănasă, C. Olaru, S, . Andrei, Java de la 0 la expert, Ed. Polirom, Ias, i, 2007.
6

[34] T. Toadere, Grafe. Teorie, algoritmi s, i aplicat, ii, Editura Albastră, Cluj-Napoca,
2002.

[35] I. Tomescu, Combinatorică s, i teoria grafurilor, Tipografia Universităt, ii din


Bucures, ti, Bucures, ti, 1978.

[36] I. Tomescu, Probleme de combinatorică s, i teoria grafurilor, Editura Didactică s, i


Pedagogică, Bucures, ti, 1981.

[37] I. Tomescu, Data structures, Editura Universităt, ii din Bucures, ti, Bucures, ti, 2004.

[38] M.A. Weiss, Data Structures and Algorithm Analysis in Java, Addison-Wesley, New
Jersey, 2012.

[39] ***, Handbook of combinatorics, edited by R.L. Graham, M. Grőtschel and L. Lovász,
Elsevier, Amsterdam, 1995.

[40] ***, 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 s, i teoria grafurilor

1.1 Notat, ii asimptotice


Vom defini un tip de funct, ii care reprezintă un bun model pentru descrierea
complexităt, ii temporale a unui algoritm, adică a dependent, ei timpului de
execut, ie fat, ă de dimensiunea datelor de intrare.

Definit, ia 1.1.1. O funct, ie asimptotic pozitivă (prescurtat a.p.) este o


funct, ie f : N \ A → R a.ı̂.

• A ⊂ N este o mult, ime finită;

• ∃ n0 ∈ N \ A astfel ı̂ncât f (n) > 0, ∀ n ≥ n0 .

Observat, ia 1.1.1. De cele mai multe ori, mult, imea A est de forma

A= {0, 1, 2, . . . , k} , unde k ∈ N.
| {z }
primele numere naturale


(3n4 + n + 3) n − 5
Exemplul 1.1.1. Funct, ia f : D → R, f (n) = , unde
(5n + 1)(n − 8)
D = {n ∈ N | n ≥ 5, n 6= 8}, este asimptotic pozitivă, deoarece D = N \ A
cu A = {0, 1, 2, 3, 4, 8} (mult, ime finită) s, i f (n) > 0, ∀ n ≥ 9.
ln(n5 + 1) − n
Exemplul 1.1.2. Funct, ia g : N \ {1, 6} → R, g(n) = , nu este
(n − 1)(n − 6)
asimptotic pozitivă, deoarece (n − 1)(n − 6) > 0, ∀ n ≥ 7, dar lim [ln(n5 +
n→∞
1) − n] = −∞, deci ∃ n0 ∈ N, n0 ≥ 7 a.ı̂. g(n) < 0, ∀ n ≥ n0 .

7
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 8

Lema 1.1.1. O funct, ie polinomială f : N → R, de grad p,

f (n) = ap · np + ap−1 · np−1 + · · · + a1 · n + a0 , a0 , a1 , . . . , ap ∈ R, ap 6= 0,

este asimptotic pozitivă dacă s, i numai dacă ap > 0.

Definit, ia 1.1.2. Fie f s, i g două funct, ii asimptotic pozitive. Spunem că f


s, i g sunt asimptotic echivalente s, i notăm

f ∼ g (sau f (n) ∼ g(n))

dacă
f (n)
∃ lim = 1.
n→∞ g(n)

Definit, ia 1.1.3. Fie g o funct, ie a.p. (asimptotic pozitivă). Definim mult, imea
de funct, ii O (g) (sau O (g(n))) ca fiind

O (g) = f f = funct, ie a.p., ∃ c > 0, ∃ n0 ∈ N a.ı̂.

f (n) ≤ c · g(n), ∀ n ≥ n0 .

• Dacă f ∈ O (g) spunem că f este asimptotic mărginită superior


de g.

• Pentru f ∈ O (g) se mai utilizează (ı̂n mod abuziv!) s, i scrierea f (n) =


O (g(n)).

• Se cites, te:

– ”f este de ordinul O mare de g” sau


– ”f (n) este de ordinul O mare de g(n) (când n → ∞)”.

Observat, ia 1.1.2. Ilustrarea grafică a notat, iei f ∈ O (g), s, i anume că pentru
n ≥ n0 graficul funct, iei c · g se află deasupra graficului funct, iei f , este dată
ı̂n Figura 1.1.1.

Definit, ia 1.1.4. Fie g o funct, ie a.p. (asimptotic pozitivă). Definim mult, imea
de funct, ii Ω(g) (sau Ω(g(n))) ca fiind

Ω(g) = f f = funct, ie a.p., ∃ c > 0, ∃ n0 ∈ N a.ı̂.

c · g(n) ≤ f (n), ∀ n ≥ n0 .

• Dacă f ∈ Ω(g) spunem că f este asimptotic mărginită inferior


de g.
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 9

Figura 1.1.1:

• Pentru f ∈ Ω(g) se mai utilizează (ı̂n mod abuziv!) s, i scrierea f (n) =


Ω(g(n)).

• Se cites, te:

– ”f este de ordinul Omega mare de g” sau


– ”f (n) este de ordinul Omega mare de g(n) (când n → ∞)”.

Observat, ia 1.1.3. Ilustrarea grafică a notat, iei f ∈ Ω(g), s, i anume că pentru
n ≥ n0 graficul funct, iei c · g se află sub graficul funct, iei f , este dată ı̂n Figura
1.1.2.
Definit, ia 1.1.5. Fie g o funct, ie a.p. (asimptotic pozitivă). Definim mult, imea
de funct, ii Θ(g) (sau Θ(g(n))) ca fiind

Θ(g) = f f = funct, ie a.p., ∃ c1 , c2 > 0, ∃ n0 ∈ N a.ı̂.

c1 · g(n) ≤ f (n) ≤ c2 · g(n), ∀ n ≥ n0 .

• Dacă f ∈ Θ(g) spunem că f este asimptotic mărginită inferior


s, i superior de g (sau că f s, i g au acelas, i ordin de cres, tere).

• Pentru f ∈ Θ(g) se mai utilizează (ı̂n mod abuziv!) s, i scrierea f (n) =


Θ(g(n)).

• Se cites, te:

– ”f este de ordinul Theta (mare) de g” sau


TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 10

Figura 1.1.2:

– ”f (n) este de ordinul Theta (mare) de g(n) (când n → ∞)”.

Observat, ia 1.1.4. Ilustrarea grafică a notat, iei f ∈ Θ(g), s, i anume că pentru
n ≥ n0 graficul funct, iei f este cuprins ı̂ntre graficele funct, iilor c1 · g s, i c2 · g,
este dată ı̂n Figura 1.1.3.

Figura 1.1.3:

Observat, ia 1.1.5. Notat, ia O se foloses, te pentru a exprima complexitatea unui


algoritm corespunzătoare timpului de execut, ie ı̂n cazul cel mai defavorabil,
fiind astfel cea mai adecvată analizei algoritmilor.
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 11

Notat, ia Ω se foloses, te pentru a exprima complexitatea unui algoritm co-


respunzătoar̄e timpului de execut, ie ı̂n cazul cel mai favorabil.
Notat, iile ∼ s, i Θ se folosesc atunci când se poate determina exact timpul
de execut, ie al unui algoritm. Notat, ia Θ se foloses, te s, i atunci când timpii de
execut, ie corespunzători cazurilor extreme sunt exprimat, i prin funct, ii care au
acelas, i ordin de cres, tere.

Propozit, ia 1.1.1. Fie f s, i g două funct, ii asimptotic pozitive.

a) f (n) = O(g(n)) dacă s, i numai dacă g(n) = Ω(f (n)).

b) f (n) = Θ(g(n)) dacă s, i numai dacă f (n) = O (g(n)) s, i f (n) = Ω(g(n)).

Propozit, ia 1.1.2. Fie f s, i g două funct, ii asimptotic pozitive astfel ı̂ncât


există
f (n)
lim = ℓ.
n→∞ g(n)

a) f (n) = O (g(n)) dacă s, i numai dacă ℓ ∈ [0, +∞).

b) f (n) = Ω(g(n)) dacă s, i numai dacă ℓ ∈ (0, +∞].

c) f (n) = Θ(g(n)) dacă s, i numai dacă ℓ ∈ (0, +∞).

Exemplul 1.1.3. Vom aplica propozit, ia anterioară


√ pentru funct, ia asimptotic
(3n4 + n + 3) n − 5
pozitivă f : D → R, f (n) = , unde D = {n ∈ N | n ≥
(5n + 1)(n − 8)
5, n 6= 8}, considerată ı̂n Exemplul 1.1.1.
Deoarece

f (n) (3n4 + n + 3) n − 5
lim = lim
n→∞ n3 n→∞ n3 (5n + 1)(n − 8)
√ 1 3
q
4
n n 3 + n3 + n4 1 − n5
= lim = 0,
n→∞ n5 (5 + n1 )(1 − n8 )

rezultă că f (n) = O (n3 ), dar f (n) 6= Ω(n3 ) s, i f (n) 6= Θ(n3 ).


Deoarece

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 )
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 12

rezultă că f (n) = Ω(n2 ), dar f (n) 6= O (n2 ) s, i 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
n4 n 3 + n13 + n34 1 − n5 3
= lim 4
√ 1 8 = ,
n→∞ n n(5 + n )(1 − n ) 5
√ √ √
rezultă că f (n) = Θ(n2 n), deci f (n) = O (n2 n) s, i f (n) = Ω(n2 n).

Propozit, ia 1.1.3. Dacă f : N → R este o funct, ie polinomială de grad p,

f (n) = ap · np + ap−1 · np−1 + · · · + a1 · n + a0 , a0 , a1 , . . . , ap ∈ R, ap > 0,

atunci
a) f (n) = O (nk ), ∀ k ≥ p;
b) f (n) = Ω(nk ), ∀ k ≤ p;
c) f (n) = Θ(np ).

Definit, ia 1.1.6. Fie A un algoritm, n dimensiunea datelor de intrare s, i


T (n) timpul de execut, ie estimat pentru algoritmul A. Se spune că algoritmul
A are comportare polinomială (sau că este polinomial sau că apart, ine
clasei P ) dacă ∃p > 0 astfel ı̂ncât T (n) = O (np ).

Observat, ia 1.1.6. Algoritmii polinomiali sunt, ı̂n general, acceptabili ı̂n prac-
tică. Algoritmii care necesită un timp de calcul exponent, ial sunt utilizat, i
numai ı̂n cazuri except, ionale s, i doar pentru date de intrare de dimensiuni
relativ mici.

1.2 Parcurgerea grafurilor. Aplicat, ii


Prin parcurgerea unui graf se ı̂nt, elege o metodă sistematică de vizitare succe-
sivă a nodurilor sale (ı̂n vederea prelucrării informat, iilor atas, ate ı̂n structura
de date modelată prin graful dat).

Definit, ia 1.2.1. Fie G = (V, E) un graf s, i x ∈ V un nod arbitrar fixat.


Parcurgerea ı̂n adâncime (DF, ”depth first”) a grafului G pornind din
nodul x, numit s, i rădăcină a acestei parcurgeri, constă ı̂n:

• se viziteză nodul x, acesta devine nod curent;


TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 13

• dacă nodul curent vi are succesori direct, i (adică noduri vj pentru care
există muchie sau arc de la vi la vj ) nevizitat, i, atunci se vizitează primul
astfel de nod vj ; nodul vj devine nod curent s, i se continuă procedeul de
parcurgere pornind din acest nod;

• dacă nodul curent vj nu mai are succesori direct, i nevizitat, i, atunci se


revine la nodul predecesor direct vi (cel din care a fost vizitat); nodul vi
redevine nod curent s, i se continuă procedeul de parcurgere pornind din
acest nod;

• dacă nodul curent nu mai are nici succesori direct, i nevizitat, i, nici prede-
cesor direct (deci este chiar radăcina x), atunci parcurgerea se ı̂ncheie.

Observat, ia 1.2.1. Pentru parcurgerea DF, considerând câte o muchie sau un


arc de la fiecare nod curent vi la primul său succesor direct nevizitat vj (care
va deveni următorul nod curent) se obt, ine un arbore, numit arbore DF.
Exemplul 1.2.1. Fie graful orientat din Figura 1.2.1.

1 2

3 4

Figura 1.2.1:

Parcurgerea ı̂n adâncime pornind din nodul 2 este

DF (2) : 2, 3, 1, 4, 5

(considerând că ordinea dintre succesorii direct, i ai fiecărui nod este ordinea
crescătoare). Arborele DF corespunzător acestei parcurgeri este reprezentat
ı̂n Figura 1.2.2.
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 14

2 1

3 4 5 2

1 4 5

Figura 1.2.2: Figura 1.2.3:

Pentru acelas, i graf, parcurgerea DF pornind din nodul 3 este


DF (3) : 3, 1, 2, 4, 5,
iar arborele DF corespunzător este reprezentat ı̂n Figura 1.2.3.
Prezentăm ı̂n continuare doi algoritmi, unul recursiv s, i altul nerecursiv,
pentru implementarea parcurgerii ı̂n adâncime.
Algoritmul 1.2.1 (parcurgerea DF, recursiv). Fie graful G = (V, E) având
mult, imea de noduri V = {1, . . . , n} s, i matricea de adiacent, ă A = (aij )i,j=1,n .
Fie x ∈ V un nod arbitrar fixat. Pentru implementarea parcurgerii DF (x)
vom utiliza un vector V IZ având semnificat, ia

1, dacă nodul i a fost vizitat,
V IZ[i] = ∀ i ∈ {1, . . . , n}.
0, ı̂n caz contrar,
Pentru memorarea arborelui DF (x) vom utiliza un vector T AT A având
semnificat, ia

0, dacă i = x (rădăcina),
T AT A[i] =
predecesorul direct al lui i, dacă i 6= x,
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 15

pentru orice nod i din parcurgerea DF .


Descrierea ı̂n pseudocod a algoritmului recursiv de parcurgere ı̂n adâncime
pornind din nodul x are forma
DF RECURSIV(x) :
VIZITEAZĂ(x); // se vizitează x, de exemplu se afis, ează x
V IZ[x] ← 1; // x a fost vizitat
for y = 1, n do
if (a[x, y] ≥ 1) and (V IZ[y] = 0) then
// y este primul succesor direct nevizitat al lui x
T AT A[y] ← x;
DF RECURSIV(y); // se continuă parcurgerea DF
// din nodul y

Programul C++ corespunzător, cu citirea grafului dintr-un fis, ier (având


pe prima linie numerele n de noduri s, i m de muchii sau arce ale grafului s, i
pe liniile următoare perechile de noduri ce formează aceste muchii sau arce)
s, i afis, area parcurgerii DF (x) s, i a vectorului T AT A (ce memorează arborele
DF (x)) este:

#include<iostream.h> //parcurgerea DF a unui graf, recursiv


#include<conio.h>
#include<fstream.h>
#define nmax 50 // nr. maxim de noduri
int n,m,A[nmax][nmax],VIZ[nmax],TATA[nmax];
void citire_graf() // citirea grafului din fisierul "graf2.dat"
{ int i,j,k;
ifstream f("graf2.dat");
f>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) A[i][j]=0;
for(k=1;k<=m;k++)
{ f>>i>>j;
A[i][j]++;
// if (j!=i) A[j][i]++; // doar pt. grafuri NEORIENTATE
}
f.close();
}
void viziteaza(int x) // vizitarea nodului x
{ cout<<x<<" ";
}
void DF_recursiv(int x) // parcurgerea DF pornind din nodul x
{ int y;
viziteaza(x);
VIZ[x]=1;
for(y=1;y<=n;y++)
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 16

if ((A[x][y]>=1)&&(VIZ[y]==0))
{ TATA[y]=x;
DF_recursiv(y);
}
}
void main()
{ int x,i;
clrscr();
citire_graf();
for(i=1;i<=n;i++)
{ VIZ[i]=0; TATA[i]=0;
}
cout<<"Nodul de pornire: x=";cin>>x;
cout<<"Parcurgerea DF: ";
DF_recursiv(x);
cout<<"\nArborele DF este dat de vectorul TATA: ";
for (i=1;i<=n;i++) cout<<TATA[i]<<" ";
getch();
}

Exemplul 1.2.2. Pentru graful din Figura 1.2.1, fis, ierul de intrare ”graf2.dat”
folosit la citirea grafului ı̂n programul anterior cont, ine datele:
5 7 //5 noduri s, i 7 arce
1 2 //arcul (1, 2)
2 3 //arcul (2, 3)
2 4 //arcul (2, 4)
2 5 //arcul (2, 5)
3 1 //arcul (3, 1)
3 2 //arcul (3, 2)
5 4 //arcul (5, 4).
Algoritmul 1.2.2 (parcurgerea DF, nerecursiv). Fie din nou G = (V, E)
un graf având mult, imea de noduri V = {1, . . . , n} s, i matricea de adiacent, ă
A = (aij )i,j=1,n . Fie x ∈ V un nod arbitrar fixat. Pentru implementarea nere-
cursivă a parcurgerii DF (x) vom utiliza vectorii V IZ s, i T AT A cu aceleas, i
semnificat, ii ca ı̂n algoritmul anterior, un vector URM cu semnificat, ia

URM[i] = următorul succesor direct al nodului i,

s, i o structură de tip stivă S, memorată ca un vector, ce cont, ine nodurile


vizitate s, i ı̂n curs de prelucrare, adică de vizitare a tuturor succesorilor.
Descrierea ı̂n pseudocod a algoritmului are forma
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 17

DF(x) :
VIZITEAZĂ(x); // se vizitează x, de exemplu se afis, ează x
V IZ[x] ← 1; // x a fost vizitat
T AT A[x] ← 0;
varf ← 1; S[varf ] ← x; // x se introduce ^ ın v^
arful stivei
while (varf > 0) do // stiva este nevidă
i ← S[varf ]; // i este nodul din v^ arful stivei
j ← URM[i] + 1; // j va fi următorul succesor direct
// nevizitat al lui i, dacă există
while (a[i, j] = 0) and (j ≤ n) do j ← j + 1;
if (j > n) then
// nodul i nu mai are succesori direct, i nevizitat, i
varf ← varf − 1; // s-a ^ıncheiat prelucrarea lui i
// s, i ^
ıl eliminăm din stivă
else
URM[i] ← j; // j este următorul succesor direct
// al lui i
if (V IZ[j] = 0) then // j nu a fost vizitat
VIZITEAZĂ(j); // se vizitează j
V IZ[j] ← 1; // j a fost vizitat
T AT A[j] ← i;
varf ← varf + 1;
S[varf ] ← j; // se introduce j ^ ın v^
arful stivei

// stiva este vidă, nu mai există noduri neprelucrate,


// parcurgerea este ı^ncheiată.

Observat, ia 1.2.2. Pentru un graf cu n noduri s, i m muchii sau arce, imple-


mentarea anterioară a parcurgerii DF are complexitatea O (n2 ), deoarece
oricare din cele n noduri este vizitat (deci introdus s, i extras din stivă) cel
mult căte o dată, iar căutarea succesorilor direct, i j nevizitat, i ai fiecărui nod
i extras din stivă se efectuează ı̂n cel mult n pas, i, prin parcurgerea liniei i
din matricea de adiacent, ă.
Dacă graful este memorat prin intermediul listelor de adiacent, ă, atunci
cautarea succesorilor direct, i j nevizitat, i ai fiecărui nod i extras din stivă
se efectuează, prin parcurgerea lor succesivă, ı̂n exact d(i) (pentru graf
P
neorientat) sau d+ (i) (pentru graf orientat) pas, i. Cum d(x) = 2m s, i
x∈V
P +
d (x) = m, obt, inem că ı̂n acest caz parcurgerea DF are complexitatea
x∈V
O (n + m).
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 18

Observat, ia 1.2.3. Dacă G = (V, E) este un graf neorientat, atunci pentru


orice nod x ∈ V componenta conexă a nodului x este (indusă de) chiar
mult, imea nodurilor vizitate prin parcurgerea DF (x).
Pe baza acestei observat, ii obt, inem următorul algoritm.
Algoritmul 1.2.3 (determinarea componentelor conexe). Fie din nou
G = (V, E) un graf neorientat, V = {1, . . . , n} s, i fie A = (aij )i,j=1,n matricea
de adiacent, ă a grafului G. Pentru determinarea componentelor conexe ale
grafului G vom utiliza un vector CC cu semnificat, ia

CC[i] = numărul componentei conexe ı̂n care se află nodul i,

∀ i ∈ {1, . . . , n} s, i o variabilă nrc ce reprezintă numărul de componente


conexe. Evident, graful G este conex dacă s, i numai dacă valoarea finală a
variabilei nrc este egală cu 1.
Descrierea ı̂n pseudocod a algoritmului are forma
COMPONENTE CONEXE :
nrc ← 0;
for i = 1, n do CC[i] ← 0;
for i = 1, n do
if (CC[i] = 0) then // nodul i nu a fost vizitat
nrc ← nrc + 1; // nodurile din parcurgerea DF (i)
DF(i); // vor forma o nouă componentă conexă

unde funct, ia DF(i) este cea din Algoritmul 1.2.1 sau cea din Algoritmul
1.2.2, adăugând instruct, iunea CC[i] ← nrc ı̂n funct, ia VIZITEAZĂ(i).
Observat, ia 1.2.4. Algoritmul anterior poate fi utilizat s, i pentru determinarea
componentelor conexe ale unui graf orientat, ı̂nlocuind condit, ia ”axy ≥ 1” din
funct, ia DF RECURSIV(x) cu ”axy ≥ 1 sau ayx ≥ 1”, respectiv condit, ia
”aij = 0” din funct, ia DF(x) cu ”aij = 0 s, i aji = 0” (deoarece ı̂n determinarea
componentelor conexe nu se t, ine cont de orientarea arcelor).
Observat, ia 1.2.5. Dacă G = (V, E) este un graf orientat, atunci pentru orice
nod x ∈ V componenta tare-conexă a nodului x este (indusă de) mult, imea
nodurilor y vizitate prin parcurgerea DF (x) a grafului G cu proprietatea că
y este vizitat s, i ı̂n parcurgerea DF (x) a grafului

G = (V, E), unde E = {(j, i)|(i, j) ∈ E},

numit transpusul (simetricul) lui G. Evident, orice drum (y, v1 , . . . , vk , x)


ı̂n graful G corespunde drumului (x, vk , . . . , v1 , y) ı̂n graful G, deci x s, i y
sunt ı̂n aceeas, i componentă tare-conexă a lui G dacă s, i numai dacă există un
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 19

drum de la x la y ı̂n G s, i un drum de la x la y ı̂n G, adică y este vizitat prin


parcurgerea DF (x) atât ı̂n G cât s, i ı̂n G.
Matricea de adiacent, ă a grafului G este transpusa matricei de adiacent, ă
a grafului G, deci pentru parcurgerea DF (x) a grafului G putem utiliza
tot matricea de adiacent, ă A a grafului dat G, ı̂nlocuind condit, ia ”aij = 0”
cu ”aji = 0”, iar condit, ia ”axy ≥ 1” cu ”ayx ≥ 1” ı̂n funct, iile DF(x),
respectiv DF RECURSIV(x). Astfel, algoritmul DF poate fi utilizat s, i
pentru determinarea componentelor tare-conexe, deci s, i pentru verificarea
tare-conexităt, ii grafului.

Definit, ia 1.2.2. Fie G = (V, E) un graf s, i x ∈ V un nod arbitrar fixat.


Parcurgerea ı̂n lăt, ime (BF,”breadth first”, parcurgerea pe nivele) a
grafului G pornind din nodul x, numit s, i rădăcină a acestei parcurgeri,
constă ı̂n:

• se viziteză nodul x, considerat nod de nivelul zero;

• se vizitează apoi succesorii direct, i nevizitat, i ai acestuia (diferit, i de x),


considerat, i noduri de nivelul 1;

• se vizitează apoi, pe rând, succesorii direct, i nevizitat, i ai acestora, con-


siderat, i noduri de nivelul 2;
s, .a.m.d.;

• parcurgerea se ı̂ncheie când niciun nod de pe un nivel nu mai are suc-


cesori direct, i nevizitat, i.

Observat, ia 1.2.6. Analog parcurgerii DF, considerând câte o muchie sau un


arc de la fiecare nod curent v al parcurgerii BF la fiecare din nodurile nevizi-
tate (de pe următorul nivel) pentru care v este predecesorul direct, se obt, ine
un arbore, numit arbore BF.
Exemplul 1.2.3. Pentru graful din Figura 1.2.1, parcurgerea ı̂n lăt, ime pornind
din nodul 2 este
BF (2) : 2, 3, 4, 5, 1
(considerând din nou ordinea dintre succesorii direct, i ai fiecărui nod ca fi-
ind ordinea crescătoare). Arborele BF corespunzător acestei parcurgeri este
reprezentat ı̂n Figura 1.2.4.
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 20

2 3

3 4 5 1 2

1 4 5

Figura 1.2.4: Figura 1.2.5:

Pentru acelas, i graf, parcurgerea BF pornind din nodul 3 este

BF (3) : 3, 1, 2, 4, 5,

iar arborele BF corespunzător este reprezentat ı̂n Figura 1.2.5.


Algoritmul 1.2.4 (parcurgerea BF). Fie graful G = (V, E) având mult, imea
de noduri V = {1, . . . , n} s, i matricea de adiacent, ă A = (aij )i,j=1,n . Fie x ∈ V
un nod arbitrar fixat. Pentru implementarea parcurgerii BF (x) vom utiliza
vectorii V IZ, T AT A, URM s, i S având aceleas, i semnificat, ii ca la parcurgerea
DF (x) (Algoritmul 1.2.2), cu deosebirea că vectorul S al nodurilor vizitate
s, i ı̂n curs de prelucrare este organizat s, i utilizat acum ca o structură de tip
coadă.
Aceasta fiind singura modificare fat, ă de Algoritmul 1.2.2, obt, inem urmă-
toarea descriere ı̂n pseudocod a algoritmului de parcurgere ı̂n lăt, ime
TEMA 1. ELEMENTE DE COMPLEX. ALG. S, I TEOR. GRAF. 21

BF(x) :
VIZITEAZĂ(x);
V IZ[x] ← 1;
T AT A[x] ← 0;
coada ← 1; // nodurile se adaugă la S pe pozit, ia "coada "
varf ← 1; // s, i se elimină de pe pozit, ia "varf "
S[coada] ← x;
while (varf ≤ coada) do // coada este nevidă
i ← S[varf ];
j ← URM[i] + 1;
while (a[i, j] = 0) and (j ≤ n) do j ← j + 1;
if (j > n) then
varf ← varf + 1;
else
URM[i] ← j;
if (V IZ[j] = 0) then
VIZITEAZĂ(j);
V IZ[j] ← 1;
T AT A[j] ← i;
coada ← coada + 1;
S[coada] ← j;

Observat, ia 1.2.7. Analog parcurgerii DF, implementarea anterioară a par-


curgerii BF are complexitatea O (n2 ), iar dacă graful este memorat prin
intermediul listelor de adiacent, ă, atunci complexitatea este O (n + m).
Observat, ia 1.2.8. Observat, iile 1.2.3, 1.2.4 s, i 1.2.5 s, i algoritmii corespunzători
rămân valabile dacă ı̂nlocuim parcurgerea DF cu parcurgerea BF.
Tema 2

Metoda Greedy

2.1 Descrierea metodei. Algoritmi generali


Metoda Greedy (a optimului local) presupune elaborarea unor strategii
de rezolvare a problemelor de optim, ı̂n care se urmăres, te maximizarea sau
minimizarea unei funct, ii obiectiv.
Se aplică problemelor ı̂n care se dă o mult, ime finită A = {a1 , a2 , . . . , an }
(mult, imea de candidat, i), cont, inând n date de intrare, pentru care se cere
să se determine o submult, ime B ⊆ A care să ı̂ndeplinească anumite condit, ii
pentru a fi acceptată. Această submult, ime se numes, te solut, ie posibilă
(solut, ie admisibilă, pe scurt solut, ie).
Deoarece, ı̂n general, există mai multe solut, ii posibile, trebuie avut ı̂n
vedere s, i un criteriu de select, ie, conform căruia, dintre acestea, să fie aleasă
una singură ca rezultat final, numită solut, ie optimă.
Solut, iile posibile au următoarele proprietăt, i:

• mult, imea vidă ∅ este ı̂ntotdeauna solut, ie posibilă;

• dacă B este solut, ie posibilă s, i C ⊆ B, atunci s, i C este solut, ie posibilă.

În continuare sunt prezentate două scheme de lucru, care urmează aceeas, i
idee, diferent, iindu-se doar prin ordinea de efectuare a unor operat, ii:
Algoritmul 2.1.1 (Metoda Greedy, varianta I).

• Se pleacă de la solut, ia vidă (∅);

• Se alege, pe rând, ı̂ntr-un anumit fel, un element din A neales la pas, ii


precedent, i.

22
TEMA 2. METODA GREEDY 23

• Dacă includerea elementului ales ı̂n solut, ia part, ială construită ante-
rior conduce la o solut, ie posibilă, atunci construim noua solut, ie prin
adăugarea 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};

Observat, ia 2.1.1.

• Funct, ia ALEGE(A, i, n) returnează un element x = aj ∈ {ai , . . . , an }


s, i efectuează interschimbarea ai ↔ aj ;

• Funct, ia SOLUTIE POSIBILA(B, x) verifică dacă B∪{x} este solut, ie


posibilă a problemei.

• Funct, ia ALEGE este cea mai dificil de realizat, deoarece trebuie să
implementeze criteriul conform căruia alegerea la fiecare pas a câte
unui candidat să conducă ı̂n final la obt, inerea solut, iei optime.

Algoritmul 2.1.2 (Metoda Greedy, varianta a II-a).


Metoda e asemănătoare primeia, cu except, ia faptului că se stabiles, te 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 };

Observat, ia 2.1.2. Prin apelul procedurii PRELUCREAZA(A, n) se efec-


tuează o permutare a elementelor mult, imii A, stabilind ordinea de analiză a
acestora. Aceasta este procedura cea mai dificil de realizat.
Observat, ia 2.1.3.
TEMA 2. METODA GREEDY 24

• Metoda Greedy nu caută să determine toate solut, iile posibile s, i apoi
să aleagă pe cea optimă conform criteriului de optimizare dat (ceea ce
ar necesita ı̂n general un timp de calcul s, i spat, iu de memorie mari), ci
constă ı̂n a alege pe rând câte un element, urmând să-l ”ı̂nghită” even-
tual ı̂n solut, ia optimă. De aici vine s, i numele metodei (Greedy = lacom).
• Astfel, dacă trebuie determinat maximul unei funct, ii de cost depinzând
de a1 , . . . , an , ideea generală a metodei este de a alege la fiecare pas acel
element care face să crească cât mai mult valoarea acestei funct, ii. Din
acest motiv metoda se mai numes, te s, i a optimului local.
• Optimul global se obt, ine prin alegeri succesive, la fiecare pas, ale op-
timului local, ceea ce permite rezolvarea problemelor fără revenire la
deciziile anterioare (as, a cum se ı̂ntâmplă la metoda backtracking).
• În general metoda Greedy oferă o solut, ie posibilă s, i nu ı̂ntotdeauna
solut, ia optimă. De aceea, dacă problema cere solut, ia optimă, algorit-
mul trebuie să fie ı̂nsot, it s, i de justificarea faptului că solut, ia generată
este optimă. Pentru aceasta, este frecvent ı̂ntâlnit următorul procedeu:
– se demonstrează prin induct, ie matematică faptul că pentru orice
pas i ∈ {0, 1, . . . , n}, dacă Bi este solut, ia posibilă construită la
pasul i, atunci există o solut, ie optimă B ∗ astfel ı̂ncât Bi ⊆ B ∗ ;
– se arată că pentru solut, ia finală, Bn , incluziunea Bn ⊆ B ∗ devine
egalitate, Bn = B ∗ , deci Bn este solut, ie optimă.
Exemplul 2.1.1. Se dă o mult, ime A = {a1 , a2 , . . . , an } cuPai ∈ R, i = 1, n. Se
cere să se determine o submult, ime B ⊆ A, astfel ı̂ncât b să fie maximă.
b∈B
Rezolvare. Dacă B ⊆ A s, i b0 ∈ B, cu b0 ≤ 0, atunci
X X
b≤ b.
b∈B b∈B\{b0 }

Rezultă că putem ı̂nt, elege prin solut, ie posibilă o submult, ime B a lui A
cu toate elementele strict pozitive.
Vom aplica metoda Greedy, ı̂n varianta I, ı̂n care
• funct, ia ALEGE furnizează x = ai ;
• funct, ia SOLUTIE POSIBILA returnează 1 (adevărat) dacă x > 0
s, i 0 (fals) ı̂n caz contrar.

TEMA 2. METODA GREEDY 25

ALEGE (A, i, n) :
x ← ai ;
returnează x;

SOLUTIE POSIBILA(B, x) :
if x > 0 then
returnează 1; // adevărat
else
returnează 0; // fals

2.2 Aplicat, ii ale Inegalităt, ii rearanjamentelor


2.2.1 Inegalitatea rearanjamentelor
Teorema 2.2.1 (Inegalitatea rearanjamentelor). Fie s, irurile crescătoare
de numere reale

a1 ≤ a2 ≤ . . . ≤ an s, i b1 ≤ b2 ≤ . . . ≤ bn , n ∈ N∗ .

Atunci, pentru orice permutare p ∈ Sn (Sn = grupul permutărilor de ordin


n), avem
X n n
X n
X
ai · bn+1−i ≤ ai · bp(i) ≤ ai · bi . (2.2.1)
i=1 i=1 i=1

Demonstrat, ie. Pentru orice permutare p ∈ Sn , notăm


n
X
s(p) = ai · bp(i) .
i=1

Fie
M = max s(p). (2.2.2)
p∈Sn

Demonstrăm că pentru orice k ∈ {0, 1, . . . , n} există p ∈ Sn astfel ı̂ncât

s(p) = M s, i p(i) = i ∀ 1 ≤ i ≤ k, (2.2.3)

prin induct, ie după k.


Pentru k = 0 afirmat, ia este evidentă, luând orice permutare p ∈ Sn astfel
ı̂ncât s(p) = M.
Presupunem (2.2.3) adevărată pentru k − 1, adică există p ∈ Sn astfel
ı̂ncât
s(p) = M s, i p(i) = i ∀ 1 ≤ i ≤ k − 1
TEMA 2. METODA GREEDY 26

s, i o demonstrăm pentru k (k ∈ {1, 2, . . . , n}).


Avem două cazuri.
Cazul 1) p(k) = k. Atunci p(i) = i ∀ 1 ≤ i ≤ k.
Cazul 2) p(k) 6= k. Cum p este o permutare s, i p(i) = i ∀ 1 ≤ i ≤ k − 1,
rezultă că p(k) > k s, i există j > k a.ı̂. p(j) = k. Definim permutarea p′ ∈ Sn
prin  ′
 p (k) = p(j),
p′ (j) = p(k),
 ′
p (i) = p(i), ∀ i ∈ {1, . . . , n} \ {k, j}.
Avem
n
X n
X

s(p ) − s(p) = ai · bp′ (i) − ai · bp(i)
i=1 i=1
= ak · bp′ (k) + aj · bp′ (j) − ak · bp(k) − aj · bp(j)
= ak · bp(j) + aj · bp(k) − ak · bp(k) − aj · bp(j)
= (aj − ak )(bp(k) − bp(j) )
= (aj − ak ) (bp(k) − bk ) ≥ 0
| {z } | {z }
≥0 ≥0

(deoarece j > k, p(k) > k, iar s, irurile (ai )i=1,n s, i (bi )i=1,n sunt crescătoare).
Deci s(p′ ) ≥ s(p) = M.
Cum, conform (2.2.2), avem s(p′ ) ≤ M, rezultă că

s(p′ ) = s(p) = M

(ı̂n plus, aj = ak sau bp(k) = bk ).


Evident, p′ (i) = i ∀ 1 ≤ i ≤ k, deci relat, ia (2.2.3) este adevărată pentru
k, ceea ce ı̂ncheie demonstrat, ia prin induct, ie a acestei relat, ii.
Luând k = n ı̂n această relat, ie rezultă că

s(e) = M, (2.2.4)

unde e ∈ Sn este permutarea identică, definită prin e(i) = i ∀ i ∈ {1, . . . , n}.


Fie p ∈ Sn o permutare arbitrară. Din (2.2.2) s, i (2.2.4) rezultă că s(p) ≤
s(e), adică
X n Xn
ai · bp(i) ≤ ai · bi .
i=1 i=1

Aplicând această inegalitate pentru s, irurile crescătoare

a1 ≤ a2 ≤ . . . ≤ an s, i − bn ≤ −bn−1 ≤ . . . ≤ −b1
TEMA 2. METODA GREEDY 27

rezultă că n n
X X
ai · (−bp(i) ) ≤ ai · (−bn+1−i ),
i=1 i=1

adică n n
X X
ai · bn+1−i ≤ ai · bp(i) .
i=1 i=1

2.2.2 Produs scalar maxim/minim


Se consideră s, irurile de numere reale

a1 , a2 , . . . , an s, i b1 , b2 , . . . , bn , n ∈ N∗ .

Se cere să se determine două permutări aq(1) , aq(2) , . . . , aq(n) s, i bp(1) , bp(2) , . . . , bp(n)
ale celor două s, iruri, q, p ∈ Sn (Sn = grupul permutărilor de ordin n), astfel
X n
ı̂ncât suma aq(i) · bp(i) să fie
i=1
a) maximă;
b) minimă.
n
X
Observat, ia 2.2.1. Suma aq(i) · bp(i) reprezintă produsul scalar al vecto-
i=1
rilor (aq(i) )i=1,n s, i (bp(i) )i=1,n . Astfel problema anterioară cere determinarea
unor permutări ale elementelor vectorilor (a1 , a2 , . . . , an ) s, i (b1 , b2 , . . . , bn ) ast-
fel ı̂ncât după permutare produsul lor scalar să fie maxim, respectiv minim.

Rezolvarea problemei de maxim


Algoritmul 2.2.1. Conform Teoremei 2.2.1 deducem următoarea strategie Greedy
ı̂n varianta I pentru rezolvarea problemei:

• Pentru obt, inerea celor n termeni ai sumei maxime, la fiecare pas i = 1, n


luăm produsul dintre:

– cel mai mic dintre termenii s, irului (a1 , a2 , . . . , an ) neales la pas, ii


anteriori;
– cel mai mic dintre termenii s, irului (b1 , b2 , . . . , bn ) neales la pas, ii
anteriori.
TEMA 2. METODA GREEDY 28

Descrierea ı̂n pseudocod a algoritmului are următoarea formă.


MAXIM1 (a, b, n, s) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )
s ← 0; // s = suma maximă
for i = 1, n do // pasul i
k ← i; // calculăm termenul minim ak din (ai , . . . , an )
m ← a[i];
for j = i + 1, n do
if a[j] < m then
k ← j;
m ← a[j];
a[i] ↔ a[k]; // interschimbăm termenii ai s, i ak
k ← i; // calculăm termenul minim bk din (bi , . . . , bn )
m ← b[i];
for j = i + 1, n do
if b[j] < m then
k ← j;
m ← b[j];
b[i] ↔ b[k]; // interschimbăm termenii bi s, i bk
s ← s + a[i] · b[i]; // adunăm produsul termenilor minimi
// la suma s
AFISARE(s, a, b, n); // se afis, ează suma maximă s, i
// permutările obt, inute
Funct, ia de afis, are este
AFISARE (s, a, b, n) :
afis, ează s;
for i = 1, n do
afis, ează a[i];
for i = 1, n do
afis, ează b[i];

Observat, ia 2.2.2. Algoritmul necesită câte două comparat, ii s, i câte cel mult
patru atribuiri pentru fiecare pereche de indici (i, j) cu i ∈ {1, 2, . . . , n} s, i
j ∈ {i + 1, i + 2, . . . , n}. Numărul acestor perechi este (n − 1) + (n − 2) +
n(n − 1)
···+2+1 = , deci algoritmul are complexitatea Θ(n2 ).
2
Algoritmul 2.2.2. Conform Teoremei 2.2.1 obt, inem s, i următoarea strategie
Greedy ı̂n varianta a II-a pentru rezolvarea problemei:

• ordonăm crescător elementele primului s, ir: a1 ≤ a2 ≤ . . . ≤ an ;


TEMA 2. METODA GREEDY 29

• ordonăm crescător elementele celui de-al doilea s, ir: b1 ≤ b2 ≤ . . . ≤ bn ;


n
X
• suma maximă este s = ai · bi .
i=1

Descrierea ı̂n pseudocod a algoritmului are următoarea formă.


MAXIM2 (a, b, n, s) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )
SORTARE (a, n); // se sortează crescător vectorul a
SORTARE (b, n); // se sortează crescător vectorul b
s ← 0; // s = suma maximă
for i = 1, n do // calculăm suma maximă s
s ← s + a[i] · b[i];
AFISARE(s, a, b, n); // se afis, ează suma maximă s, i
// permutările obt, inute
unde funct, ia de afis, are este aceeas, i ca ı̂n Algoritmul 2.2.1.
Observat, ia 2.2.3. Algoritmul anterior are complexitatea Θ(n log2 n), deoarece
necesită sortarea celor doi vectori de dimensiune n. Rezultă că Algoritmul
2.2.2 este mai eficient decât Algoritmul 2.2.1.

Rezolvarea problemei de minim


Algoritmul 2.2.3. Conform Teoremei 2.2.1 deducem următoarea strategie Greedy
ı̂n varianta I pentru rezolvarea problemei de minim:

• Pentru obt, inerea celor n termeni ai sumei minime, la fiecare pas i = 1, n


luăm produsul dintre:

– cel mai mic dintre termenii s, irului (a1 , a2 , . . . , an ) neales la pas, ii


anteriori;
– cel mai mare dintre termenii s, irului (b1 , b2 , . . . , bn ) neales la pas, ii
anteriori.

Descrierea ı̂n pseudocod a algoritmului are următoarea formă.


TEMA 2. METODA GREEDY 30

MINIM1 (a, b, n, s) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )


s ← 0; // s = suma minimă
for i = 1, n do // pasul i
k ← i; // calculăm termenul minim ak din (ai , . . . , an )
m ← a[i];
for j = i + 1, n do
if a[j] < m then
k ← j;
m ← a[j];
a[i] ↔ a[k]; // interschimbăm termenii ai s, i ak
k ← i; // calculăm termenul maxim bk din (bi , . . . , bn )
m ← b[i];
for j = i + 1, n do
if b[j] > m then
k ← j;
m ← b[j];
b[i] ↔ b[k]; // interschimbăm termenii bi s, i bk
s ← s + a[i] · b[i]; // adunăm produsul termenilor calculat, i
// la suma s
AFISARE(s, a, b, n); // se afis, ează suma minimă s, i
// permutările obt, inute
Funct, ia de afis, are este aceeas, i ca ı̂n Algoritmul 2.2.1.
Algoritmul 2.2.4. Conform Teoremei 2.2.1 obt, inem s, i următoarea strategie
Greedy ı̂n varianta a II-a pentru rezolvarea problemei de minim:

• ordonăm crescător elementele primului s, ir: a1 ≤ a2 ≤ . . . ≤ an ;

• ordonăm descrescător elementele celui de-al doilea s, ir: b1 ≥ b2 ≥ . . . ≥


bn ;
n
X
• suma minimă este s = ai · bi .
i=1

Descrierea ı̂n pseudocod a algoritmului are următoarea formă.


TEMA 2. METODA GREEDY 31

MINIM2 (a, b, n, s) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )


SORTARE1 (a, n); // se sortează crescător vectorul a
SORTARE2 (b, n); // se sortează descrescător vectorul b
s ← 0; // s = suma minimă
for i = 1, n do // calculăm suma minimă s
s ← s + a[i] · b[i];
AFISARE(s, a, b, n); // se afis, ează suma minimă s, i
// permutările obt, inute
unde funct, ia de afis, are este aceeas, i ca ı̂n Algoritmul 2.2.1.
Observat, ia 2.2.4. Analog problemei de maxim, Algoritmul 2.2.3 are comple-
xitatea Θ(n2 ), iar Algoritmul 2.2.4 are complexitatea Θ(n log2 n), fiind astfel
mai eficient decât Algoritmul 2.2.3.

2.2.3 Memorarea optimă a textelor pe benzi


Se dă o bandă magnetică suficient de lungă pentru a memora n texte (sau
fis, iere)
T1 , T2 , . . . , Tn
de lungimi date (de exemplu, ı̂n octet, i)

L1 , L2 , . . . , respectiv Ln .

La citirea unui text de pe bandă, trebuie citite s, i textele aflate ı̂naintea lui.
Presupunând că frecvent, a de citire a celor n texte este aceeas, i, se cere
să se determine o ordine de pozit, ionare (memorare) optimă a acestora pe
bandă, adică o pozit, ionare astfel ı̂ncât timpul mediu de citire să fie minim.

Modelarea problemei
• Evident, orice pozit, ionare a celor n texte pe bandă este o permutare a
vectorului (T1 , T2 , . . . , Tn ), adică are forma

(Tp(1) , Tp(2) , . . . , Tp(n) ),

unde p ∈ Sn este o permutare de ordin n (pentru orice i ∈ {1, . . . , n},


pe pozit, ia i pe bandă se memorează textul Tp(i) ).

• Evident, timpul de citire doar a unui text Tk este direct proport, ional cu
lungimea lui, deci putem considera că acest timp este egal cu lungimea
Lk a textului.
TEMA 2. METODA GREEDY 32

• Pentru orice k ∈ {1, . . . , n}, citirea textului Tp(k) necesită timpul


k
X
tk = Lp(i) ,
i=1

deoarece la timpul de citire efectivă a textului Tp(k) trebuie adăugat, i s, i


timpii de citire a textelor precedente Tp(1) , Tp(2) , . . . , Tp(k−1) .
• Frecvent, a de citire a celor n texte fiind aceeas, i, rezultă că timpul mediu
de citire pentru o pozit, ionare p ∈ Sn este
n
1X
t(p) = tk
n k=1
n k
1 XX
= Lp(i)
n k=1 i=1
n n
1 XX
= Lp(i)
n i=1 k=i
n n
!
1X X
= Lp(i) 1
n i=1 k=i
n
1X
= (n − i + 1) · Lp(i) .
n i=1

Propozit, ia 2.2.1. Dacă L1 ≤ L2 ≤ . . . ≤ Ln , atunci


min t(p) = t(e),
p∈Sn

adică pozit, ionarea corespunzătoare permutării identice este optimă.


Demonstrat, ie. Aplicând Teorema 2.2.1 pentru s, irurile crescătoare
n n−1 1
− <− < · · · < − s, i L1 ≤ L2 ≤ . . . ≤ Ln ,
n n n
rezultă că pentru orice permutare p ∈ Sn avem
n   n  
X n−i+1 X n−i+1
− · Lp(i) ≤ − · Li ,
i=1
n i=1
n
deci n n
1X 1X
(n − i + 1) · Lp(i) ≥ (n − i + 1) · Li ,
n i=1 n i=1
adică t(p) ≥ t(e). Rezultă că min t(p) = t(e).
p∈Sn
TEMA 2. METODA GREEDY 33

Observat, ia 2.2.5. Mai mult, deoarece s, irul


n n−1 1
− <− < ··· < −
n n n
este strict crescător, conform demonstrat, iei Teoremei 2.2.1 rezultă că orice
pozit, ionare optimă presupune memorarea textelor pe bandă ı̂n ordinea cres-
cătoare a lungimilor lor.
Observat, ia 2.2.6. Conform propozit, iei anterioare deducem următoarea strate-
gie Greedy pentru rezolvarea problemei:
Varianta I : La fiecare pas i = 1, n se pozit, ionează pe bandă pe pozit, ia
curenta, i, textul de lungime minimă dintre cele nepozit, ionate la pas, ii ante-
riori;
Varianta II : Se sortează textele ı̂n ordinea crescătoare a lungimilor lor s, i
se pozit, ionează pe bandă ı̂n această ordine.
Analog problemelor de la sect, iunea anterioară, Varianta I are complexi-
tatea Θ(n2 ), iar Varianta II are complexitatea Θ(n log2 n) (fiind astfel mai
eficientă decât Varianta I).

2.3 Problema rucsacului, varianta continuă


Problema rucsacului (Knapsack) este următoarea:
Se consideră un rucsac ı̂n care se poate ı̂ncărca greutatea maximă G,
unde G > 0, s, i n obiecte O1 , . . . , On , n ∈ N∗ . Pentru fiecare obiect Oi ,
i ∈ {1, . . . , n}, se cunoas, te greutatea sa, gi , unde gi > 0, s, i câs, tigul obt, inut
la transportul său ı̂n ı̂ntregime, ci , unde ci > 0.
Se cere să se determine o modalitate de incărcare a rucsacului cu obiecte
astfel ı̂ncât câs, tigul total al obiectelor ı̂ncărcate să fie maxim.
În varianta continuă (fract, ionară) a problemei, pentru fiecare obiect
Oi poate fi ı̂ncărcată orice parte (fract, iune) xi ∈ [0, 1] din el, câs, tigul obt, inut
fiind proport, ional cu partea ı̂ncărcată, adică este egal cu xi ci .

Modelarea problemei
• O solut, ie (solut, ie posibilă) a problemei este orice vector x = (x1 , . . . , xn )
astfel ı̂ncât 
xi ∈ [0, 1], ∀ i ∈ {1, . . . , n},
Pn
 xi gi ≤ G,
i=1

ultima inegalitate exprimând faptul că greutatea totală ı̂ncărcată ı̂n


rucsac nu trebuie sı̂ depăs, ească greutatea maximă.
TEMA 2. METODA GREEDY 34

• Câs, tigul (total ) corespunzător solut, iei x = (x1 , . . . , xn ) este


n
X
f (x) = xi ci .
i=1

• O solut, ie optimă a problemei este orice solut, ie x∗ = (x∗1 , . . . , x∗n ) astfel


ı̂ncât
f (x∗ ) = max{f (x) | x = solut, ie a problemei}.
• Dacă suma greutăt, ilor tuturor obiectelor este mai mică sau egală cu
Pn
greutatea maximă a rucsacului, adică gi ≤ G, atunci problema este
i=1
trivială, solut, ia x∗ = (1, 1, . . . , 1), corespunzătoare ı̂ncărcării integrale
a tuturor celor n obiecte ı̂n rucsac, fiind evident singura solut, ie optimă.
Astfel ı̂n continuare putem presupune că
n
X
gi > G. (2.3.1)
i=1

• Pentru orice solut, ie optimă x∗ = (x∗1 , . . . , x∗n ) avem


n
X
x∗i gi = G (2.3.2)
i=1

(adică rucsacul trebuie ı̂ncărcat complet). Demonstrăm această afir-


n
P
mat, ie prin reducere la absurd. Într-adevăr, dacă x∗i gi < G, cum
i=1
n
P
gi > G rezultă că există un indice k ∈ {1, . . . , n} a.ı̂. x∗k < 1.
i=1
Considerând vectorul x′ = (x′1 , . . . , x′n ) definit prin
(
x∗i , dacă i 6= k,
x′i =
x∗i + u, dacă i = k,
unde ( !)
n
1 X
u = min 1 − x∗k , G− x∗i gi ,
gk i=1
n
P n
P n
P n
P
avem u > 0, x′k ≤ 1, x′i gi = x∗i gi +ugk ≤ x∗i gi +G− x∗i gi = G
i=1 i=1 i=1 i=1
n
P n
P
s, i f (x′ ) = x′i ci = x∗i ci + uck = f (x∗ ) + uck , deci x′ este o solut, ie
i=1 i=1
a problemei s, i f (x′ ) > f (x∗ ), ceea ce contrazice optimalitatea solut, iei
x∗ .
TEMA 2. METODA GREEDY 35

Prezentăm ı̂n continuare un algoritm Greedy pentru rezolvarea problemei.


Algoritmul 2.3.1. Vom utiliza următoarea strategie Greedy:

• Ordonăm obiectele descrescător după câs, tigul lor unitar:


c1 c2 cn
≥ ≥ ··· ≥ . (2.3.3)
g1 g2 gn

• Încărcăm obiectele ı̂n rucsac, ı̂n această ordine, cât timp nu se depăs, es, te
greutatea maximă G. Încărcarea obiectelor se face ı̂n ı̂ntregime, cât
timp este posibil; ı̂n acest fel doar ultimul obiect adăugat poate fi
ı̂ncărcat part, ial.

Descrierea ı̂n pseudocod a algoritmului are următoarea formă.


RUCSAC (G, n, g, c, x, C) : // g = (g1 , . . . , gn ), c = (c1 , . . . , cn )
// C = c^ as, tigul total
SORTARE(g, c, n); // se sortează obiectele descrescător
// după c^ as, tigul lor unitar
R ← G; // R = greutatea disponibilă 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ă ı ^n rucsac
x[i] ← 1;
C ← C + c[i];
R ← R − g[i]; // actualizăm greutatea disponibilă
i ← i + 1; // trecem la obiectul următor
else
// obiectul curent nu ^ ıncape ^ ın ^ ıntregime, deci
// se adaugă exact acea parte din el care
// umple rucsacul s, i ^
ıncărcarea se ı ^ncheie
R
x[i] ← g[i] ;
C ← C + x[i]c[i];
R ← 0;
for j = i + 1, n do x[j] ← 0;
AFISARE(C, x, n); // se afis, ează c^as, tigul total maxim C
// s, i solut, ia optimă x = (x1 , . . . , xn )
TEMA 2. METODA GREEDY 36

Teorema 2.3.1 (de corectitudine a Algoritmului 2.3.1). În contex-


tul Algoritmului 2.3.1, vectorul x = (x1 , . . . , xn ) calculat de algoritm este o
solut, ie optimă a problemei rucsacului.

Demonstrat, ie. Evident, vectorul x = (x1 , . . . , xn ) calculat de algoritm verifică


relat, iile 
xi ∈ [0, 1], ∀ i ∈ {1, . . . , n},
Pn
 xi gi = G,
i=1

deci este o solut, ie a problemei. Rămâne să demonstrăm optimalitatea acestei


solut, ii.
Demonstrăm prin induct, ie după k ∈ {0, 1, . . . , n} că există o solut, ie op-
timă x∗ = (x∗1 , . . . , x∗n ) a problemei pentru care

xi = x∗i , ∀ i a.ı̂. 1 ≤ i ≤ k. (2.3.4)

Pentru k = 0 afirmat, ia este evidentă, luând x∗ orice solut, ie optimă a


problemei.
Presupunem (2.3.4) adevărată pentru k − 1, adică există o solut, ie optimă
x∗ = (x∗1 , . . . , x∗n ) a problemei pentru care

xi = x∗i , ∀ i a.ı̂. 1 ≤ i ≤ k − 1

s, i o demonstrăm pentru k (k ∈ {1, 2, . . . , n}).


Cum
k−1
X k−1
X n
X
∗ ∗ ∗
xi gi + xk gk = xi gi + xk gk ≤ x∗i gi = G,
i=1 i=1 i=1

din descrierea algoritmului (alegerea maximală a lui xk ) rezultă că

xk ≥ x∗k .

Avem două cazuri.


Cazul 1) xk = x∗k . Atunci xi = x∗i , ∀ i ∈ {1, . . . , k}, deci (2.3.4) este
adevărată pentru k.
Cazul 2) xk > x∗k . În acest caz avem k < n, deoarece dacă, prin reducere
la absurd, am avea k = n, atunci ar rezulta că
n
X n−1
X n−1
X
f (x) = xi ci = x∗i ci + xn cn > x∗i ci + x∗n cn = f (x∗ ),
i=1 i=1 i=1

ceea ce contrazice optimalitatea solut, iei x∗ .


TEMA 2. METODA GREEDY 37

Definim vectorul x∗∗ = (x∗∗ ∗∗


1 , . . . , xn ) prin
(
xi , dacă 1 ≤ i ≤ k,
x∗∗
i = (2.3.5)
α∗ x∗i , dacă k + 1 ≤ i ≤ n,
unde α∗ ∈ [0, 1) este o solut, ie a ecuat, iei
k
X n
X
h(α) = 0, unde h(α) = xi gi + α x∗i gi − G. (2.3.6)
i=1 i=k+1

O astfel de solut, ie există, deoarece


k
X n
X
h(0) = xi gi − G ≤ xi gi − G = G − G = 0,
i=1 i=1
Xk n
X k−1
X n
X
h(1) = xi gi + x∗i gi −G = x∗i gi + xk gk + x∗i gi − G
i=1 i=k+1 i=1 i=k+1
Xn
= x∗i gi − x∗k gk + xk gk − G = G + gk (xk − x∗k ) − G
i=1
= gk (xk − x∗k ) > 0,
iar h este o funct, ie continuă pe intervalul [0, 1].
Conform (2.3.5) s, i (2.3.6) rezultă că x∗∗
i ∈ [0, 1], ∀ i ∈ {1, . . . , n} s, i
n
X k
X n
X
x∗∗
i gi = xi gi + α∗ x∗i gi = h(α∗ ) + G = 0 + G = G,
i=1 i=1 i=k+1
∗∗
deci vectorul x = (x∗∗ ∗∗
1 , . . . , xn ) este o solut, ie a problemei.
Avem
k−1
X n
X n
X
∗∗ ∗
f (x ) − f (x ) = x∗i ci + xk ck + α ∗
x∗i ci − x∗i ci
i=1 i=k+1 i=1
n
X Xn
= xk ck + α∗ x∗i ci − x∗i ci
i=k+1 i=k
Xn n
X

= xk ck + α x∗i ci − x∗k ck − x∗i ci
i=k+1 i=k+1
n
X
= ck (xk − x∗k ) − (1 − α∗ ) x∗i ci
i=k+1
n
ck ∗ ∗
X ci ∗
= · (xk gk − xk gk ) − (1 − α ) · x gi . (2.3.7)
gk gi i
i=k+1
TEMA 2. METODA GREEDY 38

Conform (2.3.3) rezultă că


ci ck
≤ , ∀ i ∈ {k + 1, . . . , n}. (2.3.8)
gi gk

Din (2.3.7) s, i (2.3.8) obt, inem că


" n
#
c k
X
f (x∗∗ ) − f (x∗ ) ≥ · (xk gk − x∗k gk ) − (1 − α∗ ) x∗i gi
gk i=k+1
n n
!
ck X X
= · xk gk − x∗k gk − x∗i gi + α∗ x∗i gi
gk i=k+1 i=k+1
" n k−1
! n
#
ck X X X
= · xk gk − x∗i gi − x∗i gi + α∗ x∗i gi
gk i=1 i=1 i=k+1
k−1 n
!
ck X X
= · xk gk − G + xi gi + α∗ x∗i gi
gk i=1 i=k+1
k n
!
ck X X
= · xi gi + α∗ x∗i gi − G ,
gk i=1 i=k+1

s, i conform (2.3.6) rezultă că


ck
f (x∗∗ ) − f (x∗ ) ≥ · h(α∗ ) = 0,
gk
deci
f (x∗∗ ) ≥ f (x∗ ).
Cum x∗ este solut, ie optimă, rezultă că s, i x∗∗ este solut, ie optimă (s, i, ı̂n plus,
f (x∗∗ ) = f (x∗ )). Conform (2.3.5) avem

xi = x∗∗
i , ∀ i ∈ {1, . . . , k},

deci relat, ia (2.3.4) este adevărată pentru k, ceea ce ı̂ncheie demonstrat, ia prin
induct, ie a acestei relat, ii.
Luând k = n ı̂n această relat, ie rezultă că există o solut, ie optimă x∗ =
(x∗1 , . . . , x∗n ) pentru care

xi = x∗i , ∀ i ∈ {1, . . . , n},

deci x = x∗ s, i astfel x este o solut, ie optimă a problemei.


TEMA 2. METODA GREEDY 39

Exemplul 2.3.1. Considerăm un rucsac ı̂n care se poate ı̂ncărca o greutatea


mazimă G = 40, din n = 10 obiecte ce au greutăt, ile s, i câs, tigurile date ı̂n
următorul tabel:
Obiect O1 O2 O3 O4 O5 O6 O7 O8 O9 O10
Greutate gi 10 7 10 5 6 10 8 15 3 12
Câs, tig ci 27 9 40 20 11 20 50 22 4 33
Ordinea descrescătoare a obiectelor după câs, tigul unitar ci /gi este evident, iată
ı̂n următorul tabel:
Obiect O7 O3 O4 O10 O1 O6 O5 O8 O9 O2
Câs, tig ci 50 40 20 33 27 20 11 22 4 9
Greutate gi 8 10 5 12 10 10 6 15 3 7
Aplicarea strategiei Greedy (algoritmul de mai sus) conduce la solut, ia optimă
x = (1, 1, 1, 1, 5/10, 0, 0, 0, 0, 0),
adică umplem rucsacul ı̂ncărcând, ı̂n ordine, obiectele:
• O7 , după care greutatea disponibilă devine R = 40 − 8 = 32,
• O3 , după care R = 32 − 10 = 22,
• O4 , după care R = 22 − 5 = 17,
• O10 după care R = 17 − 12 = 5,
• 5/10 din O1 , după care R = 5 − 5 = 0.
Câs, tigul (total) obt, inut este
5
f (x) = 50 + 40 + 20 + 33 + · 27 = 156,5.
10
Observat, ia 2.3.1. Algoritmul 2.3.1 are complexitatea O (n log2 n), deoarece
este necesară sortarea obiectelor descrescător după câs, tigul unitar iar blocul
”while” se execută de cel mult n ori (câte o dată pentru fiecare obiect) s, i
necesită de fiecare dată o comparat, ie s, i 3 operat, ii aritmetice.
Observat, ia 2.3.2. În varianta discretă a problemei rucsacului, fiecare
obiect Oi poate fi ı̂ncărcat doar ı̂n ı̂ntregime. În această variantă, solut, ia
produsă de strategia Greedy (de mai sus) nu este neapărat optimă!
De eemplu, pentru datele din exemplul anterior, aplicarea strategiei Greedy
conduce la solut, ia
x = (1, 1, 1, 1, 0, 0, 0, 0, 1, 0),
adică ı̂ncărcăm ı̂n rucsac, ı̂n ordine, obiectele:
TEMA 2. METODA GREEDY 40

• O7 , după care greutatea disponibilă devine R = 40 − 8 = 32,


• O3 , după care R = 32 − 10 = 22,
• O4 , după care R = 22 − 5 = 17,
• O10 după care R = 17 − 12 = 5,
• O9 , după care R = 5 − 3 = 2 s, i nu mai există niciun obiect care să mai
ı̂ncapă ı̂n rucsac, deci ı̂ncărcarea se ı̂ncheie.
Câs, tigul (total) obt, inut este

f (x) = 50 + 40 + 20 + 33 + 4 = 147.

Solut, ia obt, inută nu este optimă, o solut, ie mai bună fiind

x′ = (1, 1, 1, 0, 1, 0, 1, 0, 0, 0),

corespunzătoare ı̂ncărcării obiectelor O7 , O3 , O4 , O1 s, i O5 , având greutatea


totală 8 + 10 + 5 + 10 + 6 = 39 (deci rucsacul nu este plin) s, i câs, tigul (total)

f (x′ ) = 50 + 40 + 20 + 27 + 11 = 148.

2.4 Problema planificării spectacolelor


Problema planificării spectacolelor este următoarea:
Se consideră n spectacole S1 , . . . , Sn , n ∈ N∗ . Pentru fiecare spectacol Si ,
i ∈ {1, . . . , n}, se cunoas, te intervalul orar Ii = [ai , bi ] de desfăs, urare, unde
ai < bi .
O persoană dores, te să vizioneze cât mai multe dintre aceste n spectacole.
Fiecare spectacol trebuie vizionat integral, nu pot fi vizionate simultan mai
multe spectacole, iar timpii necesari deplasării de la un spectacol la altul sunt
nesemnificativi (egali cu zero).
Se cere să se selecteze un număr cât mai mare de spectacole ce pot fi
vizionate de o singură persoană, cu respectarea cerint, elor de mai sus.

Modelarea problemei
• O solut, ie (solut, ie posibilă) a problemei este orice submult, ime P ⊆
{I1 , . . . , In } astfel ı̂ncât

Ii ∩ Ij = ∅, ∀ Ii , Ij ∈ P, i 6= j

(adică orice submult, ime de intervale disjuncte două cı̂te două).


TEMA 2. METODA GREEDY 41

• O solut, ie optimă a problemei este orice solut, ie P ∗ ⊆ {I1 , . . . , In } astfel


ı̂ncât
card (P ∗ ) = max{card (P ) | P = solut, ie a problemei}.
Prezentăm ı̂n continuare doi algoritmi Greedy pentru rezolvarea proble-
mei.
Algoritmul 2.4.1. Vom utiliza următoarea strategie Greedy:
• Ordonăm spectacolele crescător după timpul lor de ı̂ncheiere:
b1 ≤ b2 ≤ · · · ≤ bn . (2.4.1)
• Parcurgem spectacolele, ı̂n această ordine, s, i:
– selectăm primul spectacol;
– de fiecare dată, spectacolul curent, Si , se selectează doar dacă
nu se suprapune cu niciunul dintre spectacolele selectate anterior,
adică dacă timpul său de ı̂ncepere este mai mare decât timpul de
ı̂ncheiere al ultimului spectacol Sj selectat:
ai > bj .
Pentru memorarea solut, iei utilizăm un vector caracteristic c = (c1 , . . . , cn ),
cu semnificat, ia
(
1, dacă intervalul Ii a fost selectat,
ci =
0, ı̂n caz contrar.
Descrierea ı̂n pseudocod a algoritmului are următoarea formă.
SPECTACOLE1 (a, b, n, c, m) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )
// c = (c1 , . . . , cn ), m = numărul de spectacole selectate
SORTARE(a, b, n); // se sortează spectacolele crescător
^ncheiere bi
// după timpul lor de ı
m ← 0; // init, ializări
for i = 1, n do c[i] ← 0;
t ← a[1] − 1; // t = timpul de ^ ıncheiere al ultimului
// spectacol selectat
for i = 1, n do // parcurgem spectacolele
if a[i] > t then
c[i] ← 1; // selectăm intervalul (spectacolul) curent
m ← m + 1;
t ← b[i]; // actualizăm t
AFISARE(m, c, n); // se afis, ează numărul s, i
// submult, imea intervalelor (spectacolelor) selectate
TEMA 2. METODA GREEDY 42

Funct, ia de afis, are este


AFISARE (m, c, n) :
afis, ează m;
for i = 1, n do
if c[i] = 1 then afis, ează [a[i], b[i]];

Teorema 2.4.1 (de corectitudine a Algoritmului 2.4.1). În contextul


Algoritmului 2.4.1, submult, imea intervalelor (spectacolelor) selectate de al-
goritm este o solut, ie optimă a problemei planificării spectacolelor.
Demonstrat, ie. Fie P = {I1′ , . . . , Im

} submult, imea de intervale calculată de
algoritm, unde

I1′ = [a′1 , b′1 ], I2′ = [a′2 , b′2 ], . . . , Im = [a′m , b′m ]

sunt intervalele selectate, ı̂n această ordine, de algoritm.


Evident, m ≥ 1 (după sortare, primul interval este ı̂ntotdeauna selectat).
Din descrierea algoritmului (alegerea intervalului curent Ii′ ) rezultă că

a′i > b′i−1 , ∀ i ∈ {2, . . . , m},

deci
a′1 < b′1 < a′2 < b′2 < · · · < a′m < b′m .
Rezultă că
Ii′ ∩ Ij′ = ∅, ∀ i, j ∈ {1, . . . , m}, i 6= j,
deci submult, imea P = {I1′ , . . . , Im ′
} a intervalelor selectate de algoritm este
o solut, ie a problemei. Rămâne să demonstrăm optimalitatea acestei solut, ii.
Demonstrăm prin induct, ie după k ∈ {0, 1, . . . , m} că există o solut, ie
optimă P ∗ = {I1∗ , . . . , Ip∗ } a problemei, p ∈ N∗ , cu

I1∗ = [a∗1 , b∗1 ], I2∗ = [a∗2 , b∗2 ], . . . , Ip∗ = [a∗p , b∗p ], b∗1 < b∗2 < · · · < b∗p , (2.4.2)

pentru care
Ii′ = Ii∗ , ∀ i a.ı̂. 1 ≤ i ≤ k. (2.4.3)
Pentru k = 0 afirmat, ia este evidentă, luând P ∗ orice solut, ie optimă a
problemei (s, i sortând intervalele componente Ii∗ crescător după extremităt, ile
b∗i ).
Presupunem (2.4.3) adevărată pentru k − 1, adică există o solut, ie optimă
P ∗ = {I1∗ , . . . , Ip∗ } a problemei, ce verifică (2.4.2), pentru care

Ii′ = Ii∗ , ∀ i a.ı̂. 1 ≤ i ≤ k − 1. (2.4.4)


TEMA 2. METODA GREEDY 43

s, i o demonstrăm pentru k (k ∈ {1, 2, . . . , m}).


Din optimalitatea solut, iei P ∗ = {I1∗ , . . . , Ip∗ } rezultă că p ≥ m, deci

p ≥ m ≥ k.

Avem două cazuri.


Cazul 1) Ik′ = Ik∗ . Atunci Ii′ = Ii∗ , ∀ i ∈ {1, . . . , k}, deci (2.4.3) este
adevărată pentru k.
Cazul 2) Ik′ 6= Ik∗ , adică [a′k , b′k ] 6= [a∗k , b∗k ]. În acest caz, pentru k ≥ 2
avem a∗k > b∗k−1 (deoarece Ik∗ ∩ Ik−1

= ∅ s, i b∗k > b∗k−1 ) s, i b′k−1 = b∗k−1 (deoarece
′ ∗
Ik−1 = Ik−1 ), deci
a∗k > b′k−1 .
Atunci, din descrierea algoritmului, deoarece Ik′ = [a′k , b′k ] este primul interval

selectat după intervalul Ik−1 = [a′k−1 , b′k−1 ], rezultă că

b′k ≤ b∗k . (2.4.5)

Din descrierea algoritmului, această inegalitate este valabilă s, i pentru k = 1,


deoarece I1′ = [a′1 , b′1 ] este primul interval selectat.
Definim submult, imea de intervale P ∗∗ = {I1∗∗ , . . . , Ip∗∗ } prin
(
Ii∗ , dacă i 6= k,
Ii∗∗ = [a∗∗
i , b∗∗
i ] = (2.4.6)
Ii′ , dacă i = k.

Deoarece P ∗ = {I1∗ , . . . , Ip∗ } este solut, ie a problemei s, i verifică (2.4.2), rezultă


că

a∗1 < b∗1 < a∗2 < b∗2 < · · · < a∗k−1 < b∗k−1 < a∗k < b∗k <
< a∗k+1 < b∗k+1 < · · · < a∗p < b∗p . (2.4.7)

Pentru k ≥ 2 avem a′k > b′k−1 (din descrierea algoritmului) s, i b′k−1 = b∗k−1
′ ∗
(deoarece Ik−1 = Ik−1 ), deci
a′k > b∗k−1 . (2.4.8)
Din (2.4.7), (2.4.8) s, i (2.4.5) rezultă că

a∗1 < b∗1 < a∗2 < b∗2 < · · · < a∗k−1 < b∗k−1 < a′k < b′k <
< a∗k+1 < b∗k+1 < · · · < a∗p < b∗p

(inegalitate valabilă s, i pentru k = 1), deci submult, imea P ∗∗ = {I1∗∗ , . . . , Ip∗∗ },


definită de (2.4.6), este o solut, ie a problemei s, i

b∗∗ ∗∗ ∗∗
1 < b2 < · · · < bp .
TEMA 2. METODA GREEDY 44

Cum
card (P ∗∗ ) = p = card (P ∗)
s, i P ∗ este solut, ie optimă, rezultă că s, i P ∗∗ este solut, ie optimă.
Conform (2.4.6) s, i (2.4.4) avem

Ii′ = Ii∗∗ , ∀ i ∈ {1, . . . , k},

deci relat, ia (2.4.3) este adevărată pentru k, ceea ce ı̂ncheie demonstrat, ia prin
induct, ie a acestei relat, ii.
Luând k = m ı̂n această relat, ie rezultă că există o solut, ie optimă P ∗ =
{I1∗ , . . . , Ip∗ } pentru care

Ii′ = Ii∗ , ∀ i ∈ {1, . . . , m}.

Demonstrăm că p = m prin reducere la absurd. Într-adevăr, dacă p > m



atunci ar exista intervalul Im+1 = [a∗m+1 , b∗m+1 ] astfel ı̂ncât

a∗m+1 > b∗m = b′m

ceea ce ar contrazice faptul că algoritmul se ı̂ncheie cu selectarea intervalului



Im = [a′m , b′m ].
Astfel p = m, deci

P = {I1′ , . . . , Im

} = {I1∗ , . . . , Ip∗ } = P ∗

s, i astfel submult, imea P este o solut, ie optimă a problemei.

Exemplul 2.4.1. Considerăm n = 14 spectacole ce au timpii de ı̂ncepere s, i


de ı̂ncheiere dat, i ı̂n următorul tabel (ı̂n ordinea crescătoare a timpilor de
ı̂ncepere ai ):

Spectacol S1 S2 S3 S4 S5 S6 S7
Timp de ı̂ncepere ai 8:00 8:10 8:15 8:50 9:10 9:20 9:20
Timp de ı̂ncheiere bi 9:10 9:00 9:00 10:20 10:40 10:30 11:00
Spectacol S8 S9 S10 S11 S12 S13 S14
Timp de ı̂ncepere ai 10:45 11:00 12:00 12:10 12:30 13:00 13:40
Timp de ı̂ncheiere bi 12:00 12:30 13:30 14:00 13:50 14:30 15:00

Ordonarea spectacolele crescător după timpul lor de ı̂ncheiere bi este


evident, iată ı̂n următorul tabel:
TEMA 2. METODA GREEDY 45

Spectacol S2 S3 S1 S4 S6 S5 S7
Timp de ı̂ncepere ai 8:10 8:15 8:00 8:50 9:20 9:10 9:20
Timp de ı̂ncheiere bi 9:00 9:00 9:10 10:20 10:30 10:40 11:00
Spectacol S8 S9 S10 S12 S11 S13 S14
Timp de ı̂ncepere ai 10:45 11:00 12:00 12:30 12:10 13:00 13:40
Timp de ı̂ncheiere bi 12:00 12:30 13:30 13:50 14:00 14:30 15:00
Aplicarea strategiei Greedy din algoritmul de mai sus conduce la solut, ia
optimă dată de selectarea (vizionarea), ı̂n ordine, a spectacolelor:
• S2 (primul, ı̂n ordinea impusă),
• S6 (primul situat după S2 s, i care are timpul de ı̂ncepere mai mare decât
timpul de ı̂ncheiere al lui S2 ),
• S8 (primul situat după S6 s, i care are timpul de ı̂ncepere mai mare decât
timpul de ı̂ncheiere al lui S6 ),
• S12 (primul situat după S8 s, i care are timpul de ı̂ncepere mai mare
decât timpul de ı̂ncheiere al lui S8 ), după care nu mai urmează niciun
spectacol care să ı̂nceapă după ı̂ncheierea lui S12 , deci selectarea se
termină.
Numărul maxim de spectacole ce pot fi vizionate este deci egal cu 4.
Observat, ia 2.4.1. Algoritmul 2.4.1 are complexitatea O (n log2 n), deoarece
este necesară sortarea spectacolelor crescător după timpul lor de ı̂ncheiere,
iar blocul ”for” prin care se parcurg spectacolele se execută de n ori (câte
o dată pentru fiecare spectacol) s, i necesită de fiecare dată o comparat, ie, cel
mult o adunare s, i cel mult 3 operat, ii de atribuire.
Algoritmul 2.4.2. O altă rezolvare a problemei spectacolelor se obt, ine prin
utilizarea următoarei strategie Greedy, similară cu cea de mai sus.
• Ordonăm spectacolele descrescător după timpul lor de ı̂ncepere:
a1 ≥ a2 ≥ · · · ≥ an .

• Parcurgem spectacolele, ı̂n această ordine, s, i:


– selectăm primul spectacol;
– de fiecare dată, spectacolul curent, Si , se selectează doar dacă
nu se suprapune cu niciunul dintre spectacolele selectate anterior,
adică dacă timpul său de ı̂ncheiere este mai mic decât timpul de
ı̂ncepere al ultimului spectacol Sj selectat:
bi < aj .
TEMA 2. METODA GREEDY 46

Pentru memorarea solut, iei se utilizează din nou un vector caracteristic


c = (c1 , . . . , cn ), cu aceeas, i semnificat, ie ca ı̂n algoritmul de mai sus.
Descrierea ı̂n pseudocod a noului algoritm are următoarea formă.
SPECTACOLE2 (a, b, n, c, m) : // a = (a1 , . . . , an ), b = (b1 , . . . , bn )
// c = (c1 , . . . , cn ), m = numărul de spectacole selectate
SORTARE(a, b, n); // se sortează spectacolele crescător
// după timpul lor de ı ^ncepere ai
m ← 0; // init, ializări
for i = 1, n do c[i] ← 0;
t ← b[n] + 1; // t = timpul de ^ ıncepere al ultimului
// spectacol selectat
for i = n, 1, −1 do // parcurgem spectacolele ı ^n ordinea
// descrescătoare a timpilor de ı ^ncepere
if b[i] < t then
c[i] ← 1; // selectăm intervalul (spectacolul) curent
m ← m + 1;
t ← a[i]; // actualizăm t
AFISARE(m, c, n); // se afis, ează numărul s, i
// submult, imea intervalelor (spectacolelor) selectate
Funct, ia de afis, are este aceeas, i ca ı̂n Algoritmul 2.4.1.
Observat, ia 2.4.2. Demonstrat, ia corectitudinii s, i evaluarea complexităt, ii Al-
goritmului 2.4.2 sunt analoage cu cele ale Algoritmul 2.4.1.
Exemplul 2.4.2. Pentru spectacolele din Exemplul 2.4.1, ordonate crescător
după timpii lor de ı̂ncepere ai ı̂n primul tabel, aplicarea strategiei Greedy
din Algoritmul 2.4.2 conduce la solut, ia optimă dată de următoarea selectare
(vizionare ı̂n ordine inversă) a spectacolelor:
• S14 (ultimul, ı̂n ordinea crescătoare a timpilor de ı̂ncepere),
• S10 (ultimul situat ı̂nainte de S14 s, i care are timpul de ı̂ncheiere mai
mic decât timpul de ı̂ncepere al lui S14 ),
• S7 (ultimul situat ı̂nainte de S10 s, i care are timpul de ı̂ncheiere mai mic
decât timpul de ı̂ncepere al lui S10 ),
• S3 (ultimul situat ı̂nainte de S7 s, i care are timpul de ı̂ncheiere mai mic
decât timpul de ı̂ncepere al lui S7 ), ı̂nainte de care nu mai avem niciun
spectacol care să se ı̂ncheie ı̂nainte de ı̂nceperea lui S3 , deci selectarea
se termină.
Numărul maxim de spectacole ce pot fi vizionate este egal, din nou, cu 4.
TEMA 2. METODA GREEDY 47

2.5 Arbori part, iali de cost minim


Definit, ia 2.5.1. Un graf ponderat este o pereche (G, c), unde G = (V, E)
este un graf iar c : E → R este o funct, ie numită pondere (cost). Pentru
orice e ∈ E, c(e) se numes, te ponderea (costul) muchiei sau arcului e.

Definit, ia 2.5.2. Fie (G, c) un graf ponderat, G = (V, E).

a) Dacă H = (U, F ) este un subgraf al lui G, atunci costul (ponderea)


lui H este X
c(H) = c(e)
e∈F

(adică suma costurilor muchiilor sau arcelor sale).

b) Un arbore part, ial T ⋆ = (V, F ) al lui G cu proprietatea că

c(T ⋆ ) = min{c(T )|T = arbore part, ial al lui G}

se numes, te arbore part, ial de cost minim (APM) al grafului pon-


derat (G, c).

Observat, ia 2.5.1. Un graf ponderat are arbori part, iali de cost minim dacă s, i
numai dacă este conex.
Problema determinării arborilor part, iali de cost minim are numeroase
aplicat, ii practice. Prezentăm ı̂n continuare doi algoritmi fundamentali pentru
rezolvarea acestei probleme.
Algoritmul 2.5.1 (Kruskal). Fie (G, c) un graf ponderat conex cu G =
(V, E), V = {v1 , . . . , vn }. Algoritmul are n − 1 pas, i.

• La pasul i, i = 1, n − 1, dintre muchiile neselectate la pas, ii anteriori


se selectează o muchie ei ∈ E de cost minim cu proprietatea că nu
formează cicluri cu muchiile {e1 , . . . , ei−1 } selectate la pas, ii anteriori.

Algoritmul 2.5.2 (Prim). Fie (G, c) un graf ponderat conex cu G = (V, E),
V = {v1 , . . . , vn }. Algoritmul are n pas, i.

• La pasul 0 se selectează un nod arbitrar x0 ∈ V .

• La pasul i, i = 1, n − 1, se selectează o muchie ei = [xj , xi ] ∈ E de cost


minim cu proprietatea că are ca extremităt, i un nod xj ∈ V selectat la
un pas anterior s, i celălalt nod xi ∈ V neselectat la pas, ii anteriori; se
selectează s, i nodul xi .
TEMA 2. METODA GREEDY 48

Teorema 2.5.1 (de corectitudine a algoritmilor Kruskal s, i Prim). În


contextul Algoritmilor Kruskal sau Prim, fie F = {e1 , . . . , en−1 } mult, imea
muchiilor selectate. Atunci T = (V, F ) este un arbore part, ial de cost minim
al grafului ponderat (G, c).

Demonstrat, ie. Vom prezenta o demonstrat, ie comună a corectitudinii celor


doi algoritmi. Fie T0 = (V, ∅) s, i Ti = (V, {e1 , . . . , ei }), ∀ i ∈ {1, 2, . . . , n − 1},
unde e1 , e2 , . . . , en−1 sunt muchiile selectate, ı̂n această ordine, de Algoritmul
Kruskal sau de Algoritmul Prim.
Graful G fiind conex, selectarea muchiei ei este posibilă la fiecare pas i,
iar Ti este o pădure part, ială a lui G (afirmat, ie evidentă pentru Algoritmul
Kruskal, iar pentru Algoritmul Prim este o consecint, ă a faptului că nodurile
neselectate la pasul i sunt izolate ı̂n Ti ).
Demonstrăm prin induct, ie după i ∈ {0, 1, . . . , n − 1} că există un APM
T = (V, F ⋆ ) astfel ı̂ncât

Ti ⊆ T ⋆ (adică {e1 , . . . , ei } ⊆ F ⋆ ). (2.5.1)

Pentru i = 0 afirmat, ia este evidentă, luând T ⋆ orice APM (există, deoarece


G este conex).
Presupunem (2.5.1) adevărată pentru i − 1, adică există T ⋆ = (V, F ⋆ )
APM cu Ti−1 ⊆ T ⋆ s, i o demonstrăm pentru i (i ∈ {1, 2, . . . , n − 1}).
Fie ei = [xj , xi ] muchia selectată de Algoritmul Kruskal sau de Algoritmul
Prim la pasul i. În cazul Algoritmului Prim, xj este nodul selectat la un pas
anterior (j ≤ i − 1). Avem două cazuri.
Cazul 1) ei ∈ F ⋆ . Atunci {e1 , . . . , ei } ⊆ F ⋆ , deci Ti ⊆ T ⋆ .
Cazul 2) ei 6∈ F ⋆ . Conform Teoremei numărului ciclomatic, graful H =
T ⋆ + ei = (V, F ⋆ ∪ {ei }) obt, inut din T ⋆ prin adăugarea muchiei ei cont, ine un
ciclu elementar unic

Ci = [xj , w0 , . . . , wk , xi , xj ]

având ultima muchie chiar muchia ei . Cum Ti = Ti−1 + ei este o pădure,


rezultă că xj s, i xi sunt ı̂n componente conexe diferite ale lui Ti−1 (ı̂n caz
contrar Ti ar cont, ine un ciclu de forma [xj , y0, . . . , yr , xi , xj ] având ultima
muchie ei ). Rezultă că lant, ul elementar

µi = [xj , w0 , . . . , wk , xi ]

(obt, inut din ciclul Ci prin eliminarea muchiei ei ) cont, ine o muchie e′i = [x′ , y ′]
astfel ı̂ncât x′ este ı̂n aceeas, i componentă conexă cu xj ı̂n pădurea Ti−1 , iar y ′
nu este ı̂n această componentă conexă. Evident, rezultă că e′i nu este muchie
TEMA 2. METODA GREEDY 49

a lui Ti−1 , adică e′i 6∈ {e1 , . . . , ei−1 }, iar graful Ti′ = Ti−1 + e′i nu cont, ine
cicluri. De asemenea, e′i 6= ei , deci e′i ∈ F ∗ .
Pe de o parte, din descrierea Algoritmului Kruskal deducem că

c(ei ) ≤ c(e′i )

(deoarece muchia e′i nu formează cicluri cu {e1 , . . . , ei−1 }, deci ei fiind muchia
selectată la pasul i verifică această inegalitate).
Pe de altă parte, din descrierea Algoritmului Prim deducem că la pasul
i nodul x′ era deja selectat la un pas anterior (fiind ı̂n aceeas, i componentă
conexă cu xj ı̂n Ti−1 ), iar nodul y ′ nu era selectat la un pas anterior (nefiind
ı̂n acea componentă conexă), deci din nou avem

c(ei ) ≤ c(e′i )

(ei fiind muchia selectată la pasul i verifică această inegalitate).


Continuăm demonstrat, ia comună pentru cei doi algoritmi. Fie

T ⋆⋆ = (T ⋆ + ei ) − e′i

graful part, ial al lui G obt, inut din T ⋆ prin adăugarea muchiei ei s, i eliminarea
muchiei e′i , adică T ⋆⋆ = (V, F ⋆⋆ ), unde F ⋆⋆ = F ⋆ ∪ {ei } \ {e′i }.
Evident, T ⋆⋆ este conex (T ⋆ este conex iar ı̂ntre nodurile x′ s, i y ′ după eli-
minarea muchiei e′i rămâne lant, ul obt, inut din ciclul Ci prin eliminarea acestei
muchii) s, i are n−1 muchii (deoarece T ⋆ are n−1 muchii). Conform Teoremei
numărului ciclomatic rezultă că T ⋆⋆ este un arbore part, ial al grafului G.
Deoarece c(ei ) ≤ c(e′i ) obt, inem

c(T ⋆⋆ ) ≤ c(T ⋆ )

s, i cum T ⋆ este un APM rezultă că s, i T ⋆⋆ este un APM (s, i, ı̂n plus, c(T ⋆⋆ ) =
c(T ⋆ )). Cum Ti ⊆ T ⋆⋆ , demonstrat, ia prin induct, ie a relat, iei (2.5.1) este
completă.
Luând i = n − 1 ı̂n această relat, ie obt, inem că T ⊆ T ⋆ , unde T = Tn−1 =
(V, F ), F = {e1 , . . . , en−1 } (mult, imea muchiilor selectate de algoritm) iar T ⋆
este un APM. Dar T s, i T ⋆ au fiecare câte n − 1 muchii, deci T = T ⋆ s, i astfel
T este un APM al grafului dat.
Exemplul 2.5.1. Fie graful ponderat (G, c) reprezentat ı̂n Figura 2.5.1, unde
costul fiecărei muchii este scris lângă segmentul corespunzător acesteia.
TEMA 2. METODA GREEDY 50

30 50 100
1 2 3 4
20
90
70 60 6
110 70 120

0
15
5 80
40
10
7 8 9 10
100 30 130

Figura 2.5.1:

Aplicarea Algoritmului Kruskal este evident, iată ı̂n următorul tabel:


Pas Muchia selectată Costul ei
1 [5, 8] 10
2 [3, 6] 20
3 [1, 2] 30
4 [8, 9] 30
5 [2, 3] 50
6 [2, 5] 60
7 [4, 6] 90
8 [7, 8] 100
9 [4, 10] 120
Arborele part, ial de cost minim obt, inut este reprezentat ı̂n Figura 2.5.2. Cos-
tul acestui APM este de 510.

30 50
1 2 3 4
20
90
60 6
120
5
10
7 8 9 10
100 30

Figura 2.5.2:
TEMA 2. METODA GREEDY 51

Aplicarea Algoritmului Prim pentru acelas, i graf este evident, iată ı̂n ur-
mătorul tabel:
Pas Muchia selectată 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 part, ial de cost minim obt, inut este deci acelas, i cu cel obt, inut
prin aplicarea Algoritmului Kruskal.
Observat, ia 2.5.2. Algoritmii Kruskal s, i Prim sunt specifici metodei de
programare Greedy. Algoritmul Kruskal selectează muchii, ı̂n ordinea
crescătoare a costurilor, subgrafurile induse pe parcurs de acestea nefiind
neapărat conexe. Algoritmul Prim selectează muchii s, i noduri, nu neapărat
ı̂n ordinea crescătoare a costurilor muchiilor, iar subgrafurile induse pe par-
curs de muchiile selectate sunt conexe.
În implementări optime, se poate arăta că Algoritmul Kruskal are com-
plexitatea O (m ln n) (fiind necesară sortarea muchiilor după cost), iar Algo-
ritmul Prim are complexitatea O (n2 ) ı̂n cazul memorării grafului prin ma-
tricea de adiacent, ă (o astfel de implementare va fi prezentată ı̂n continuare),
unde n s, i m reprezintă numerele de noduri, respectiv de muchii ale grafului
dat. Graful fiind conex, m ≥ n − 1.
Pentru grafuri simple, m ≤ n(n−1) 2
. Folosind s, i inegalitatea ln n ≤ n − 1,
obt, inem că Algoritmul Kruskal este mai eficient pentru grafuri ”sărace” ı̂n
muchii, iar Algoritmul Prim este mai eficient pentru grafuri ”bogate” ı̂n
muchii.
Observat, ia 2.5.3. Pentru implementarea Algoritmului Kruskal, memorăm
graful ponderat conex (G, c), unde G = (V, E), V = {1, . . . , n}, E =
{e1 , . . . , em }, ı̂ntr-o matrice cu 3 linii s, i m coloane P = (pik ) i = 1, 3 având
k = 1, m
semnificat, ia:

dacă ek = [xk , yk ] ∈ E, atunci p1k = xk , p2k = yk s, i p3k = c(ek ).


TEMA 2. METODA GREEDY 52

Utilizăm un vector S cu semnificat, ia



1, dacă ek a fost selectată,
S[k] =
0, ı̂n caz contrar,

∀ k ∈ {1, . . . , m} s, i un vector CC cu semnificat, ia


CC[i] = numărul componentei conexe ı̂n care se află nodul i ı̂n graful
indus de muchiile selectate, ∀ i ∈ {1, . . . , n}.
Astfel o muchie [x, y] nu formează cicluri cu muchiile selectate dacă s, i numai
dacă
CC[x] 6= CC[y].
Descrierea ı̂n pseudocod a algoritmului are următoarea formă.
KRUSKAL :
SORTARE(P ); // se sortează coloanele matricei P
// crescător după costurile muchiilor
for i = 1, m do S[i] ← 0;
for i = 1, n do CC[i] ← i;
cost ← 0; // costul APM
poz ← 0; // căutarea următoarei muchii ek ce va fi
// selectată ^ ıncepe de pe pozit, ia poz + 1
for l = 1, n − 1 do // pasul l
k ← poz;
repeat
k ← k + 1; x ← p1k ; y ← p2k ; c ← p3k ;
while (CC[x] = CC[y]);
S[k] ← 1; // selectăm ek = [x, y]
cost ← cost + c; poz ← k;
aux ← CC[y]; // actualizăm vectorul CC prin unificarea
// componentelor conexe ale lui x s, i y
for i = 1, n do
if (CC[i] = aux) then CC[i] ← CC[x];

Observat, ia 2.5.4. Pentru implementarea Algoritmului Prim, memorăm graful


ponderat conex s, i simplu (G, c), unde G = (V, E), V = {1, . . . , n}, E =
{e1 , . . . , em }, cu ajutorul unei matrice C = (cij )i,j=1,n a costurilor (directe)
având semnificat, ia

 c([i, j]), dacă [i, j] ∈ E,
cij = 0, dacă i = j, (2.5.2)

∞, ı̂n rest,
TEMA 2. METODA GREEDY 53

∀ i, j ∈ {1, . . . , n}. Pentru grafuri neorientate, matricea C este simetrică. În


cazul grafurilor nesimple putem lua
cij = min{c(e)|e = [i, j] ∈ E}.
Utilizăm un vector S cu semnificat, ia

1, dacă nodul i a fost selectat,
S[i] =
0, ı̂n caz contrar
s, i doi vectori t s, i T AT A având semnificat, ia
t[i] = costul minim al unei muchii [i, j] de la nodul i la un nod selectat j,
T AT A[i] = nodul j ce atinge minimul ı̂n t[i], ∀ i ∈ {1, . . . , n}.
Descrierea ı̂n pseudocod a algoritmului are următoarea formă.
PRIM :
S[1] ← 1; // selectăm nodul 1
cost ← 0; // costul APM
for i = 2, n do // init, ializări
S[i] ← 0; t[i] ← ci1 ; T AT A[i] ← 1;
for l = 1, n − 1 do // căutăm nodul y s, i muchia [x, y]
// ce vor fi selectate la pasul l
min ← ∞;
for i = 2, n do
if (S[i] = 0) and (t[i] < min) then
min ← t[i]; y ← i;
S[y] ← 1; // selectăm nodul y
x ← T AT A[y]; // s, i muchia [x, y]
cost ← cost + cxy ;
for i = 2, n do // actualizăm vectorii t s, i T AT A
if (S[i] = 0) and (t[i] > ciy ) then
t[i] ← ciy ; T AT A[i] ← y;

2.6 Distant, e s, i drumuri minime. Algoritmul


lui Dijkstra
Problema determinării distant, elor s, i drumurilor minime ı̂ntre nodurile unui
graf ponderat apare ı̂n numeroase aplicat, ii practice. În continuare vom
prezenta un algoritm clasic pentru rezolvarea acestei probleme.
TEMA 2. METODA GREEDY 54

Definit, ia 2.6.1. Fie (G, c) un graf ponderat, unde G = (V, E), V = {v1 , . . . ,
vn } iar c : E → R+ .

a) Dacă µ = (x0 , e1 , x1 , . . . , xk−1 , ek , xk ) este un drum al grafului G, unde


x0 , x1 , . . . , xk ∈ V , e1 , . . . , ek ∈ E, k ∈ N, atunci costul (ponderea)
lui µ este

 0, dacă k = 0,
c(µ) = k
P
 c(ei ), dacă k ≥ 1
i=1

(adică suma costurilor arcelor sau muchiilor sale).

b) Fie x, y ∈ V . Un drum µ⋆ = (x, . . . , y) ı̂n graful G cu proprietatea că

c(µ⋆ ) = min{c(µ)|µ este drum de la x la y ı̂n G}

se numes, te drum minim (drum de cost minim, drum de pon-


dere minimă) de la x la y ı̂n graful ponderat (G, c). Costul c(µ⋆ )
al acestui drum minim se numes, te distant, a minimă de la x la y ı̂n
graful (G, c).

Observat, ia 2.6.1. Eliminând eventualele circuite C1 , . . . , Cp dintr-un drum


µ de la nodul x la nodul y obt, inem un drum elementar µ′ de la x la y cu
p
P
proprietatea că c(µ′ ) = c(µ) − c(Ck ) ≤ c(µ).
k=1
Dacă drumul µ este minim atunci s, i drumul elementar µ′ este minim s, i
c(e) = 0 pentru orice muchie sau arc e al circuitelor C1 , . . . , Cp . Deci existent, a
unui drum minim de la x la y implică existent, a unui drum minim elementar
de la x la y. Astfel distant, a minimă de la x la y poate fi considerată ca fiind
costul minim al unui drum elementar de la x la y. Mai mult, dacă funct, ia
cost c este strict pozitivă, atunci orice drum minim este elementar.
Observat, ia 2.6.2. Mult, imea drumurilor elementare fiind evident finită, avem
echivalent, a: există drumuri minime de la x la y dacă s, i numai dacă există
drumuri de la x la y.
Observat, ia 2.6.3. Distant, a minimă de la un nod x la el ı̂nsus, i este egală cu
zero, drumul minim elementar de la x la x fiind drumul de lungime zero,
µ = (x).
Observat, ia 2.6.4. Dacă µ = (x0 , x1 , . . . , xk ) este un drum minim de la x0 la
xk , atunci orice subdrum µ′ = (xi , xi+1 , . . . , xj ) (0 ≤ i ≤ j ≤ k) al său este
un drum minim de la xi la xj (principiul optimalităt, ii al lui Bellman).
Afirmat, ia poate fi justificată us, or prin reducere la absurd.
TEMA 2. METODA GREEDY 55

Exemplul 2.6.1. Fie graful ponderat (G, c) reprezentat ı̂n Figura 2.6.1.

10

5
5 5
3 5 4
15

10
5

Figura 2.6.1:

Drumurile elementare de la nodul 1 la nodul 5 sunt µ1 = (1, 3, 5), având


costul c(µ1 ) = 10 + 5 = 15, µ2 = (1, 4, 5), având costul c(µ2 ) = 5 + 5 = 10,
deci µ2 este un drum minim de la 1 la 5. Astfel distant, a minimă de la nodul
1 la nodul 5 este c(µ2 ) = 10.
Definit, ia 2.6.2. Fie (G, c) un graf ponderat, unde G = (V, E), V = {v1 , . . . ,
vn }, c : E → R+ .
a) Matricea distant, elor (costurilor) directe asociată grafului (G, c)
este matricea C = (cij )i,j=1,n definită prin

 0, dacă i = j,
cij = min{c(e)|e = (vi , vj ) ∈ E}, dacă i 6= j s, i ∃ (vi , vj ) ∈ E,

∞, dacă i 6= j s, i 6 ∃ (vi , vj ) ∈ E

(pentru grafuri neorientate (vi , vj ) desemnând de fapt muchia [vi , vj ]).


b) Matricea distant, elor (costurilor) minime asociată grafului (G, c)
este matricea C ⋆ = (c⋆ij )i,j=1,n definită prin

 c(µ⋆ ), µ⋆ = drum minim de la vi la vj ,

cij = dacă ∃ µ = (vi , . . . , vj ) drum ı̂n G,

∞, ı̂n caz contrar.

Observat, ia 2.6.5. Evident, pentru orice graf neorientat atât matricea distan-
t, elor directe cât s, i matricea distant, elor minime sunt matrice simetrice.
TEMA 2. METODA GREEDY 56

Observat, ia 2.6.6. Conform Observat, iei 2.6.1, putem să ı̂nlocuim termenul de
”drum” cu cel de ”drum elementar” ı̂n definit, ia anterioară.
Conform Observat, iei 2.6.2, punctul b) din definit, ia anterioară este o ex-
tindere a definit, iei distant, ei minime de la punctul b) al Definit, iei 2.6.1.
Conform Observat, iei 2.6.3, c⋆ii = 0 ∀ i ∈ {1, . . . , n}.
Exemplul 2.6.2. Matricele distant, elor directe, respectiv minime asociate gra-
fului din Exemplul 2.6.1 sunt
   
0 15 10 5 ∞ 0 15 10 5 10
 ∞ 0 ∞ ∞ ∞   ∞ 0 ∞ ∞ ∞ 
  ⋆
 
C =  ∞ 5 0 ∞ 5 , C = 
 
 10 5 0 15 5  .

 ∞ 10 ∞ 0 5   10 10 20 0 5 
5 5 ∞ ∞ 0 5 5 15 10 0

Vom expune ı̂n continuare un algoritm pentru determinarea distant, elor


minime s, i a drumurilor minime de la un nod fixat, numit s, i nod sursă, la
toate nodurile grafului ponderat dat.
Algoritmul 2.6.1 (Dijkstra). Fie (G, c) un graf ponderat, G = (V, E), V =
{v1 , v2 , . . . , vn }, c : E → R+ . Fie C = (cij )i,j=1,n matricea distant, elor di-
recte asociată grafului (G, c) s, i fie vs ∈ V un nod arbitrar fixat, numit nod
sursă. Distant, ele minime de la nodul vs la nodurile grafului sunt calculate
s, i memorate ı̂ntr-un vector t = (t1 , . . . , tn ) astfel:

• La pasul 1 se selectează nodul sursă vs s, i se ia ts = 0;

• La pasul k, 2 ≤ k ≤ n, se cunosc nodurile vi1 , . . . , vik−1 selectate la


pas, ii anteriori s, i distant, ele corespondente ti1 , . . . , tik−1 .
a) Dacă nu mai există nici-o muchie sau arc de la un nod selectat
vj ∈ {vi1 , . . . , vik−1 } la un nod neselectat vi ∈ V \{vi1 , . . . , vik−1 }, atunci
se ia ti = ∞ pentru orice nod neselectat vi ∈ V \ {vi1 , . . . , vik−1 } s, i
algoritmul se ı̂ncheie.
b) În caz contrar se selectează un nod vik ∈ V \ {vi1 , . . . , vik−1 } cu
proprietatea că există un nod selectat vjk ∈ {vi1 , . . . , vik−1 } astfel ı̂ncât

tjk + cjk ik = min{tj + cji |vj ∈ {vi1 , . . . , vik−1 }, vi ∈ V \ {vi1 , . . . , vik−1 }}.
(2.6.1)

Se ia

tik = tjk + cjk ik (2.6.2)

s, i se trece la pasul k + 1.
TEMA 2. METODA GREEDY 57

Observat, ia 2.6.7. Evident, algoritmul execută cel mult n pas, i.


Teorema 2.6.1 (de corectitudine a Algoritmului Dijkstra). În contex-
tul Algoritmului Dijkstra, avem

ti = c⋆si , ∀ i ∈ {1, . . . , n}

(adică distant, a ti calculată de algoritm este chiar distant, a minimă de la vs


la vi ).
Demonstrat, ie. Vom demonstra prin induct, ie după k că nodul vik selectat la
pasul k s, i distant, a corespondentă tik calculată la acel pas verifică egalitatea
din enunt, , adică

tik = c⋆sik ,

s, i, ı̂n plus, tik < ∞.


Pentru k = 1 afirmat, ia este evidentă deoarece

vi1 = vs , ti1 = 0 = c⋆ss .

Presupunem adevărată afirmat, ia pentru orice pas mai mic decât k s, i o


demonstrăm pentru pasul k. Fie vjk ∈ {vi1 , . . . , vik−1 } un nod ce verifică ega-
litatea (2.6.1). Din descrierea algoritmului s, i din ipoteza de induct, ie (nodul
vjk fiind selectat la un pas anterior), rezultă că tjk = c⋆sjk < ∞ s, i cjk ik < ∞,
deci tik < ∞ (conform (2.6.2)).
Dacă (vs , . . . , vjk ) este un drum minim de la vs la vjk (există, deoarece
c⋆sjk < ∞), atunci µ = (vs , . . . , vjk , vik ) este un drum de la vs la vik , având
costul c(µ) = c⋆sjk + cjk ik = tjk + cjk ik = tik (conform (2.6.2)), deci

c⋆sik ≤ tik < ∞. (2.6.3)

Rezultă că există drumuri minime de la vs la vik . Fie

µ⋆ = (vs = x0 , x1 , . . . , xp−1 , xp = vik )

un drum elementar minim de la vs la vik . Fie l ∈ {0, 1, . . . , p − 1} indicele


maxim astfel ı̂ncât xl ∈ {vi1 , . . . , vik−1 } (există, deoarece x0 = vs = vi1 ).
Fie xl = vir , 1 ≤ r ≤ k − 1, s, i fie xl+1 = viq , q ≥ k.
Din descrierea pasului q al algoritmului, conform relat, iilor (2.6.1) s, i (2.6.2)
rezultă că

tiq ≤ tir + cir iq ,


TEMA 2. METODA GREEDY 58

iar conform ipotezei de induct, ie pentru r avem

tir = c⋆sir < ∞.

Deci

tiq ≤ c⋆sir + cir iq = c⋆siq (2.6.4)

(conform principiului optimalităt, ii al lui Bellman pentru subdrumurile dintre


x0 = vs s, i xl = vir , respectiv dintre x0 = vs s, i xl+1 = viq ale drumului minim
µ⋆ ).
Cazul 1) Dacă l = p − 1. atunci xl+1 = vik , deci q = k s, i din (2.6.3) s, i
(2.6.4) rezultă că tik = c⋆sik < ∞.
Cazul 2) Dacă l < p − 1, deci q 6= k, demonstrăm că

tik = c⋆sik

prin reducere la absurd. Într-adevăr, ı̂n caz contrar conform (2.6.3) am avea
c⋆sik < tik .
Cum q > k, din descrierea algoritmului avem tiq ≥ tik (deoarece valorile
tik sunt monoton crescătoare de la un pas la altul, induct, ie!). Utilizând
(2.6.4) am obt, ine
c⋆sik < tik ≤ tiq ≤ c⋆siq ,
ceea ce contrazice faptul că are loc inegalitatea c⋆siq ≤ c⋆sik (conform principiu-
lui optimalităt, ii al lui Bellman pentru subdrumul dintre vs s, i viq al drumului
minim µ⋆ ).
Demonstrat, ia prin induct, ie este ı̂ncheiată.
Evident, pentru orice nod vi rămas neselectat ı̂n urma executării ultimului
pas al algoritmului avem ti = ∞ = c⋆si .
Într-adevăr, dacă ar exista un drum elementar minim

µ = (vs = y0 , y1 , . . . , yp = vi ),

luând l ∈ {0, 1, . . . , p − 1} indicele maxim pentru care yl este selectat (există,


deoarece y0 = vs este selectat) atunci yl+1 ar fi neselectat des, i există o muchie
sau un arc de la yl la yl+1 , contradict, ie cu descrierea modului de ı̂ncheiere a
algoritmului.
Exemplul 2.6.3. Pentru graful ponderat din Exemplul 2.6.1, luând ca nod
sursă nodul 1, aplicarea Algoritmului Dijkstra este evident, iată ı̂n următorul
tabel:
TEMA 2. METODA GREEDY 59

Pas Nodul selectat Distant, a minimă


1 1 0
2 4 5
3 3 10
4 5 10
5 2 15
De exemplu, la pasul 3 avem deja selectate nodurile i1 = 1 s, i i2 = 4, cu
distant, ele minime t1 = c⋆11 = 0 s, i t4 = c⋆14 = 5. Se selectează nodul i3 = 3,
cu distant, a minimă t3 = 10, deoarece

min{t1 + c12 , t1 + c13 , t1 + c15 , t4 + c42 , t4 + c43 , t4 + c45 }


= min{0 + 15, 0 + 10, 0 + ∞, 5 + 10, 5 + ∞, 5 + 5} = 10 = t1 + c13 .

Observat, ia 2.6.8. Algoritmul Dijkstra este specific metodei de programare


Greedy, el selectând nodurile ı̂n ordinea crescătoare a distant, ei fat, ă de nodul
sursă.
Observat, ia 2.6.9. Pentru implementarea Algoritmului Dijkstra, considerăm
că V = {1, . . . , n} s, i că nodul sursă este s ∈ V . Utilizăm un vector S având
semnificat, ia

1, dacă nodul i a fost selectat,
S[i] = ∀ i ∈ {1, . . . , n}
0, ı̂n caz contrar,

s, i un vector t având semnificat, ia


t[i] = distant, a minimă de la nodul sursă s la nodul i, ∀ i ∈ {1, . . . , n},
calculat conform (2.6.1) s, i (2.6.2).
Pentru determinarea drumurilor minime de la nodul s la nodurile grafului
vom utiliza s, i un vector T AT A având semnificat, ia
T AT A[i] = nodul j ce este predecesorul direct al nodului i pe drumul
minim de la s la i, ∀ i ∈ {1, . . . , n}.
Astfel ı̂n vectorul T AT A se memorează un arbore compus din drumuri
minime de la nodul sursă la nodurile grafului, numit arborele drumurilor
minime.
Dacă i = ik este nodul selectat la pasul k, atunci j = jk se determină
conform egalităt, ii (2.6.1).
Descrierea ı̂n pseudocod a algoritmului are forma următoare.
TEMA 2. METODA GREEDY 60

DIJKSTRA(s) :
for i = 1, n do // init, ializări
S[i] ← 0; t[i] ← ∞; T AT A[i] ← ∞;
t[s] ← 0; T AT A[s] ← 0; // s este nodul sursă
repeat
// selectăm următorul nod x, ^ ın ordinea crescătoare
// 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ă x, ı
^l selectăm
S[x] ← 1;
for i = 1, n do // actualizăm 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.6.4. Pentru graful ponderat din Exemplul 2.5.1, luând ca nod
sursă nodul s = 1, aplicarea Algoritmului Dijkstra este evident, iată ı̂n următorul
tabel:
Pas Nodul selectat x T AT A[x] Distant, a minimă t[x]
1 1 0 0
2 2 1 30
3 5 1 70
4 3 2 80
5 8 5 80
6 6 3 100
7 7 1 110
8 9 5 110
9 4 3 180
10 10 9 240
Arborele drumurilor minime, memorat ı̂n vectorul T AT A, este reprezen-
tat ı̂n Figura 2.6.2.
TEMA 2. METODA GREEDY 61

30 50 100
1 2 3 4
20
70 6
110
5
40
10
7 8 9 10
130

Figura 2.6.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].

Observat, ia 2.6.10. Implementarea anterioară necesită O (n2 ) operat, ii (deoa-


rece blocul ”repeat” se execută de cel mult n ori s, i necesită de fiecare dată
cel mult n comparat, ii pentru determinarea nodului selectat x s, i cel mult n
comparat, ii s, i n adunări pentru actualizarea vectorilor t s, i T AT A). Aceasta
este de fapt s, i complexitatea Algoritmului Dijkstra (ı̂n implementarea op-
timă) ı̂n cazul memorării grafului prin matricea distant, elor directe.
TEMA 2. METODA GREEDY 62

2.7 Fluxuri maxime ı̂n ret, ele


Definit, ia 2.7.1. O ret, ea (ret, ea de transport) are forma R = (G, s, t, c),
unde:

• G = (V, E) este un graf orientat simplu.


V se numes, te s, i mult, imea nodurilor ret, elei, iar E se numes, te s, i
mult, imea arcelor ret, elei;

• s, t ∈ V sunt două noduri a.ı̂. s 6= t.


Nodul s se numes, te nodul sursă (intrarea) al ret, elei, iar nodul t se
numes, te nodul destinat, ie (ies, irea) al ret, elei;

• c : E → R+ este o funct, ie numită funct, ie capacitate.


Pentru orice e ∈ E, c(e) se numes, te capacitatea arcului e.

Pentru simplificarea notat, iilor, extindem funct, ia capacitate


(
c(i, j), dacă (i, j) ∈ E,
c : V × V → R+ , c(i, j) = (2.7.1)
0, dacă (i, j) 6∈ E.

Exemplul 2.7.1. În Figura 2.7.1 este reprezentată o ret, ea R, capacităt, ile fiind
ment, ionate pe arce. Considerăm că această ret, ea are intrarea s = 1 s, i ies, irea
t = 6.

Figura 2.7.1:
TEMA 2. METODA GREEDY 63

Definit, ia 2.7.2. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). Un flux
ı̂n ret, eaua R este o funct, ie f : V × V → R ce verifică următoarele două
proprietăt, i:

0 ≤ f (i, j) ≤ c(i, j), ∀i, j ∈ V, (2.7.2)


X X
f (j, i) = f (i, j), ∀i ∈ V \ {s, t}. (2.7.3)
j∈V j∈V

f (i, j) reprezintă fluxul transportat pe arcul (i, j).


Relat, ia (2.7.2) se numes, te condit, ia de mărginire a fluxului, iar
relat, ia (2.7.3) se numes, te condit, ia de conservare a fluxului.
Observat, ia 2.7.1. Evident,

f (i, j) = 0 ∀(i, j) 6∈ E,

deci, analog funct, iei capacitate c, s, i funct, ia flux f poate fi definită (restrânsă)
doar pe mult, imea arcelor ret, elei (adică f : E → R).
Observat, ia 2.7.2. Definit, iile s, i rezultatele din această sect, iune sunt valabile
s, i pentru ret, ele formate cu grafuri orientate oarecare (nu neapărat simple).
În acest caz general funct, iile capacitate s, i flux se definesc neapărat doar pe
colect, ia (multisetul) E a arcelor ret, elei.
Observat, ia 2.7.3. În particular, f (i, j) = 0 ∀i, j ∈ V este un flux ı̂n orice
ret, ea, numit fluxul nul.
Exemplul 2.7.2. Pentru ret, eaua din Figura 2.7.1, un exemplu de flux este
reprezentat ı̂n Figura 2.7.2. Pe fiecare arc (i, j) sunt ment, ionate fluxul f (i, j)
s, i capacitatea c(i, j), ı̂n această ordine.

Figura 2.7.2:
TEMA 2. METODA GREEDY 64

Lema 2.7.1. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). Pentru orice flux
f ı̂n ret, eaua R are loc egalitatea
!
X X X X
f (i, t) − f (t, i) = − f (i, s) − f (s, i) .
i∈V i∈V i∈V i∈V

Definit, ia 2.7.3. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). Pentru orice
flux f ı̂n ret, eaua R, numărul
!
X X X X
v(f ) = f (i, t) − f (t, i) = − f (i, s) − f (s, i)
i∈V i∈V i∈V i∈V

se numes, te valoarea fluxului f (fluxul net ce ajunge la nodul destinat, ie,


fluxul net ce iese din nodul sursă).
Exemplul 2.7.3. Fluxul din Figura 2.7.2 are valoarea v(f ) = 2 + 6 = 8.
Definit, ia 2.7.4. Fie R = (G, s, t, c) o ret, ea. Un flux f ∗ ı̂n ret, eaua R cu
proprietatea că

v(f ∗) = max{v(f ) | f = flux ı̂n R}

se numes, te flux de valoare maximă (flux maxim) ı̂n ret, eaua R.


Problema determinării fluxurilor maxime ı̂ntr-o ret, ea are numeroase a-
plicat, ii practice. În continuare vom prezenta doi algoritmi clasici pentru
rezolvarea acestei probleme.
Începem cu definirea unor not, iuni ajutătoare.
Definit, ia 2.7.5. Dacă µ = [x0 , x1 , . . . , xk ] este un lant, elementar ı̂n gra-
ful orientat G = (V, E), atunci arcele sale de forma (xi , xi+1 ) ∈ E (i ∈
{0, . . . , k − 1}) se numesc arce directe pentru lant, ul µ, iar arcele sale de
forma (xi+1 , xi ) ∈ E (i ∈ {0, . . . , k − 1}) se numesc arce inverse pentru
lant, ul µ.
Exemplul 2.7.4. Pentru graful din Figura 2.7.2, lant, ul [1, 2, 3, 4, 5, 6] are arcele
directe (1, 2), (2, 3), (4, 5), (5, 6) s, i arcul invers (4, 3).
Definit, ia 2.7.6. Fie f un flux ı̂n ret, eaua R = (G, s, t, c). Un C-lant, ı̂n
ret, eaua R relativ la fluxul f este un lant, elementar µ ı̂n graful G ce verifică
următoarele două proprietăt, i:

f (i, j) < c(i, j), ∀(i, j) = arc direct al lui µ,


f (i, j) > 0, ∀(i, j) = arc invers al lui µ.
TEMA 2. METODA GREEDY 65

Definit, ia 2.7.7. Fie f un flux ı̂n ret, eaua R = (G, s, t, c) s, i fie µ un C-lant,
ı̂n ret, eaua R relativ la fluxul f .

a) Pentru orice arc (i, j) al lui µ, numărul


(
c(i, j) − f (i, j), dacă (i, j) este arc direct al lui µ,
rµ (i, j) =
f (i, j), dacă (i, j) este arc invers al lui µ

se numes, te capacitatea reziduală (reziduul) a arcului (i, j) relativ


la C-lant, ul µ.

b) Numărul
r(µ) = min{rµ (i, j) | (i, j) = arc al lui µ}
se numes, te capacitatea reziduală (reziduul) a C-lant, ului µ.

Observat, ia 2.7.4. Conform definit, iilor anterioare, pentru orice C-lant, µ avem
r(µ) > 0.
Exemplul 2.7.5. Pentru ret, eaua s, i fluxul reprezentate ı̂n Figura 2.7.2, lant, ul
µ = [1, 2, 3, 4, 5, 6] este un C-lant, . Reziduurile pe arcele acestui C-lant, sunt

rµ (1, 2) = 3 − 2 = 1, rµ (2, 3) = 4 − 1 = 3, rµ (4, 3) = 5,

rµ (4, 5) = 3 − 2 = 1, rµ (5, 6) = 7 − 2 = 5,
deci reziduul pe acest C-lant, este r(µ) = 1.
Definit, ia 2.7.8. Fie f un flux ı̂n ret, eaua R = (G, s, t, c). Un C-lant, de la s
la t ı̂n ret, eaua R relativ la fluxul f se numes, te lant, de cres, tere (ı̂n ret, eaua
R relativ la fluxul f ).
Exemplul 2.7.6. Lant, ul µ = [1, 2, 3, 4, 5, 6] din exemplul anterior este un lant,
de cres, tere.
Lema 2.7.2. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). Fie f un flux ı̂n
ret, eaua R s, i fie µ un lant, de cres, tere ı̂n ret, eaua R relativ la fluxul f . Atunci
funct, ia f ′ : V × V → R definită prin

f (i, j) + r(µ), dacă (i, j) este arc direct al lui µ,


f (i, j) = f (i, j) − r(µ), dacă (i, j) este arc invers al lui µ,


f (i, j), dacă (i, j) nu este arc al lui µ

este un flux ı̂n ret, eaua R s, i

v(f ′ ) = v(f ) + r(µ).


TEMA 2. METODA GREEDY 66

Observat, ia 2.7.5. În contextul lemei anterioare, conform Observat, iei 2.7.4
avem
v(f ′ ) = v(f ) + r(µ) > v(f ).
Inegalitatea justifică denumirea lui µ drept lant, de cres, tere a fluxului f , iar
egalitatea justifică denumirea lui r(µ) drept capacitatea reziduală a lant, ului
µ.
Definit, ia 2.7.9. Fluxul f ′ definit ı̂n lema anterioară se numes, te fluxul
obt, inut prin mărirea fluxului f de-a lungul lant, ului de cres, tere
µ s, i se notează cu
f ′ = f ⊕ r(µ).
Exemplul 2.7.7. Pentru ret, eaua R s, i fluxul f reprezentate ı̂n Figura 2.7.2,
lant, ul µ = [1, 2, 3, 4, 5, 6] este un lant, de cres, tere având reziduul r(µ) = 1.
Fluxul f ′ = f ⊕ r(µ) obt, inut prin aplicarea lemei anterioare este reprezentat
ı̂n Figura 2.7.3. Valoarea acestui flux este v(f ′ ) = v(f ) + r(µ) = 8 + 1 = 9.

Figura 2.7.3:

Definit, ia 2.7.10. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). O sect, iune
(tăietură) ı̂n ret, eaua R este o pereche (S, T ), S, T ⊆ V , ce verifică urmă-
toarele proprietăt, i:

S ∪ T = V, S ∩ T = ∅,
s ∈ S, t ∈ T.

Observat, ia 2.7.6. Dacă (S, T ) este o sect, iune ı̂n ret, eaua R = (G, s, t, c), unde
G = (V, E), atunci V = S ∪ T este o partit, ie a mult, imii V a nodurilor ret, elei
(adică V = S ∪ T , S 6= ∅, T 6= ∅, S ∩ T = ∅) a.ı̂. s ∈ S s, i t ∈ T . Rezultă
TEMA 2. METODA GREEDY 67

că numărul de sect, iuni ale ret, elei R este egal cu numărul de submult, imi
S \ {s} ⊆ V \ {s, t}, deci cu

2n−2, unde n = card (V ).

Definit, ia 2.7.11. Fie R = (G, s, t, c) o ret, ea, unde G = (V, E). Pentru
orice sect, iune (S, T ) ı̂n ret, eaua R, numărul
XX
c(S, T ) = c(i, j)
i∈S j∈T

se numes, te capacitatea sect, iunii (S, T ).


Observat, ia 2.7.7. Conform relat, iei (2.7.1), capacitatea unei sect, iuni (S, T )
este suma capacităt, ilor tuturor arcelor ce au extremitatea init, ială ı̂n S s, i
extremitatea finală ı̂n T .
Exemplul 2.7.8. Pentru ret, eaua reprezentată ı̂n Figura 2.7.1,

(S, T ) = ({1, 2, 5}, {3, 4, 6})

este o sect, iune având capacitatea

c(S, T ) = c(1, 4) + c(2, 3) + c(2, 4) + c(5, 6) = 10 + 4 + 2 + 7 = 23.

Lema 2.7.3. Fie R = (G, s, t, c) o ret, ea. Pentru orice flux f s, i orice sect, iune
(S, T ) ı̂n ret, eaua R avem
XX
v(f ) = (f (i, j) − f (j, i))
i∈S j∈T

(adică valoarea fluxului este egală cu fluxul net ce traversează sect, iunea).
Lema 2.7.4. Fie R = (G, s, t, c) o ret, ea.

a) Pentru orice flux f s, i orice sect, iune (S, T ) ı̂n ret, eaua R avem

v(f ) ≤ c(S, T ).

b) Dacă f ∗ este un flux s, i (S ∗ , T ∗) este o sect, iune ı̂n ret, eaua R astfel ı̂ncât

v(f ∗ ) = c(S ∗ , T ∗ ),

atunci f ∗ este un flux de valoare maximă s, i (S ∗ , T ∗ ) este o sect, iune de


capacitate minimă ı̂n ret, eaua R.
TEMA 2. METODA GREEDY 68

Teorema 2.7.1 (de caracterizare a unui flux de valoare maximă).


Fie R = (G, s, t, c) o ret, ea. Un flux f ı̂n ret, eaua R este un flux de valoare
maximă dacă s, i numai dacă nu există lant, uri de cres, tere ı̂n ret, eaua R relativ
la fluxul f .
Demonstrat, ie. ”⇒” Fie f un flux de valoare maximă ı̂n R. Dacă ar exista
un lant, de cres, tere µ ı̂n R relativ la fluxul f , atunci conform Lemei 2.7.2 ar
rezulta că funct, ia f ′ = f ⊕r(µ) ar fi un flux ı̂n R s, i v(f ′ ) = v(f )+r(µ) > v(f )
(conform Observat, iei 2.7.5) contradict, ie. Deci nu există lant, uri de cres, tere
ı̂n R relativ la fluxul f .
”⇐” Fie f un flux ı̂n R a.ı̂. nu există lant, uri de cres, tere ı̂n R relativ la
f . Fie
(
S = {i ∈ V | există C-lant, uri de la s la i ı̂n R relativ la f },
T = {i ∈ V | nu există C-lant, uri de la s la i ı̂n R relativ la f }.
(2.7.4)
Evident, S ∪ T = V s, i S ∩ T = ∅.
De asemenea, avem s ∈ S (deoarece [s] este un C-lant, de la s la s ı̂n R
relativ la f ) s, i t ∈ T (deoarece nu există lant, uri de cres, tere, adică C-lant, uri
de la s la t ı̂n R relativ la f ). Deci (S, T ) este o sect, iune ı̂n ret, eaua R.
Fie i ∈ S s, i j ∈ T arbitrar fixat, i. Deoarece i ∈ S rezultă că există un C-
lant, µ = [s = x0 , x1 , . . . , xk = i] ı̂n R relativ la f . Atunci x0 , x1 , . . . , xk ∈ S
(sublant, urile C-lant, ului µ sunt tot C-lant, uri), deci j 6∈ V (µ).
Dacă am avea f (i, j) < c(i, j) sau f (j, i) = 0, atunci ar rezulta că [s =
x0 , x1 , . . . , xk = i, j] ar fi un C-lant, ı̂n R relativ la f , ceea ce ar contrazice
apartenent, a j ∈ T . Deci
f (i, j) = c(i, j) s, i f (j, i) = 0,
pentru orice i ∈ S s, i j ∈ T .
Aplicând Lema 2.7.3, avem
XX XX
v(f ) = (f (i, j) − f (j, i)) = (c(i, j) − 0) = c(S, T ),
i∈S j∈T i∈S j∈T

deci conform Lemei 2.7.4 rezultă că f este un flux de valoare maximă ı̂n
ret, eaua R (iar (S, T ) este o sect, iune de capacitate minimă ı̂n ret, eaua R).
Observat, ia 2.7.8. Dacă se cunoas, te un flux f de valoare maximă ı̂ntr-o ret, ea
R, atunci formulele (2.7.4) determină o sect, iune (S, T ) de capacitate minimă,
deci orice algoritm pentru determinarea unui flux de valoare maximă bazat
pe caracterizarea dată ı̂n teorema anterioară rezolvă s, i problema determinării
unei sect, iuni de capacitate minimă.
TEMA 2. METODA GREEDY 69

Definit, ia 2.7.12. Fie f un flux ı̂n ret, eaua R = (G, s, t, c), unde G = (V, E).
Funct, ia r : V × V → R+ definită prin

c(i, j) − f (i, j), dacă f (i, j) < c(i, j),

r(i, j) = f (j, i), dacă f (j, i) > 0 s, i f (i, j) = c(i, j),


0, ı̂n rest

se numes, te capacitatea reziduală (reziduul) a ret, elei R relativ la fluxul


f , iar graful orientat Gf = (V, Ef ) definit prin

Ef = {(i, j) ∈ V × V | r(i, j) > 0}

se numes, te graful rezidual al ret, elei R relativ la fluxul f .


Observat, ia 2.7.9. Fie f un flux ı̂n ret, eaua R = (G, s, t, c). Fie r s, i Gf
capacitatea reziduală, respectiv graful rezidual ale ret, elei R relativ la fluxul
f . Fie µ = [x0 , x1 , . . . , xk ] un lant, elementar ı̂n graful G. Evident, avem
echivalent, ele:

µ este un C-lant, ı̂n R relativ la f ⇔ r(xi , xi+1 ) > 0, ∀i ∈ {0, . . . , k − 1} ⇔


⇔ (x0 , x1 , . . . , xk ) este un drum elementar ı̂n graful rezidual Gf ;
µ este un lant, de cres, tere ı̂n R relativ la f ⇔
⇔ (x0 , x1 , . . . , xk ) este un drum elementar de la s la t ı̂n graful rezidual Gf .

Exemplul 2.7.9. Pentru ret, eaua R s, i fluxul f ′ reprezentate ı̂n Figura 2.7.3,
graful rezidual Gf ′ este reprezentat ı̂n Figura 2.7.4, capacităt, ile reziduale
fiind ment, ionate pe arce.
(1, 4, 2, 3, 6) este un drum elementar ı̂n graful rezidual Gf ′ , deci µ′ =
[1, 4, 2, 3, 6] este un lant, de cres, tere ı̂n ret, eaua R relativ la fluxul f ′ .
TEMA 2. METODA GREEDY 70

Figura 2.7.4:

Conform rezultatelor de mai sus obt, inem următorul algoritm pentru de-
terminarea unui flux de valoare maximă ı̂ntr-o ret, ea.
Algoritmul 2.7.1 (Ford-Fulkerson). Fie R = (G, s, t, c) o ret, ea, unde G =
(V, E).
Conform Teoremei 2.7.1, schit, a algoritmului, descrisă ı̂n pseudocod, are
următoarea formă.
FORD FULKERSON :
f ← 0; // sau f ← f0 , unde f0 este un flux
// disponibil init, ial
repeat
if (EXISTĂ LANT , DE CRES , TERE) then
// există lant, uri de cres, tere
// relativ la fluxul curent f
µ ← LANT , DE CRES , TERE; // se determină
// un astfel de lant, de cres, tere
f ← f ⊕ r(µ); // se măres, te valoarea fluxului curent,
// de-a lungul lant, ului de cres, tere
while (EXISTĂ LANT , DE CRES , TERE);
// nu mai există lant, uri de cres, tere,
// deci fluxul curent este de valoare maximă
AFIS, ARE(f ); // se afis, ează fluxul de valoare maximă
În continuare detaliem implementarea acestui algoritm. Presupunem că

V = {1, 2, . . . , n}, s = 1, t = n,
TEMA 2. METODA GREEDY 71

cu n ≥ 2.
Pentru depistarea s, i memorarea eventualelor lant, uri de cres, tere relativ la
fluxul curent vom utiliza doi vectori SEL s, i T AT A având semnificat, ia

1, dacă există un C-lant, de la nodul s = 1 la nodul i,
SEL[i] =
0, ı̂n caz contrar,

T AT A[i] =predecesorul direct al nodului i pe C-lant, ul


de la nodul s = 1 la nodul i,

∀i ∈ {1, . . . , n}.
Algoritmul descris ı̂n pseudocod are următoarea formă (detaliată).
TEMA 2. METODA GREEDY 72

FORD FULKERSON :
CITIRE RET , EA; // se cites, te ret, eaua dată
for i = 1, n do
for j = 1, n do fij ← 0; // fluxul init, ial
vmax ← 0; // valoarea fluxul maxim
repeat // se caută lant, uri de cres, tere a fluxului curent,
// folosind Observat, ia 2.7.9
CALCUL REZIDUURI; // se determină reziduul s, i
// graful rezidual ale ret, elei relativ la fluxul curent
SEL[1] ← 1; // se selectează nodul sursă
for i = 2, n do SEL[i] ← 0;
T AT A[1] ← 0; // pt. memorarea C-lant, urilor
// ce pornesc din nodul sursă
DF(1); // se parcurge graful rezidual, memor^ and
// C-lant, urile ce pornesc din nodul sursă;
// parcurgerea DF, poate fi ı ^nlocuită cu
// parcurgerea BF (Algoritmul Edmonds-Karp )
if (SEL[n] = 1) then // s-a selectat nodul destinat, ie,
// deci există lant, de cres, tere a fluxului
rmin ← ∞; // reziduul minim, de-a lungul
// lant, ului de cres, tere
DET LANT CR; // se determină lant, ul de cres, tere
// a fluxului s, i reziduul minim
MĂRIRE FLUX; // se măres, te fluxul curent, de-a
// lungul lant, ului de cres, tere
vmax ← vmax + rmin;; // se actualizează valoarea
// fluxului curent
while (SEL[n] = 1);
// nu mai există lant, uri de cres, tere a fluxului,
// deci fluxul curent este maxim
AFIS, ARE REZULTATE;
// se afis, ează fluxul maxim s, i valoarea sa,
// eventual s, i sect, iunea de capacitate minimă,
// calculată conform (2.7.4) astfel:
// S = {i ∈ {1, . . . , n} | SEL[i] = 1},
// T = {i ∈ {1, . . . , n} | SEL[i] = 0}
Funct, iile utilizate sunt descrise ı̂n continuare.
TEMA 2. METODA GREEDY 73

CALCUL REZIDUURI :
for i = 1, n do
for j = 1, n do
if (fij < cij ) then
rij ← cij − fij ;
else
if (fji > 0) then
rij ← fji ;
else
rij ← 0;

DF(i) : // recursiv
for j = 1, n do
if (rij > 0 and SEL[j] = 0) then
T AT A[j] ← i; SEL[j] ← 1;;
DF(j);

DET LANT CR : // se determină reziduul minim de-a


// lungul lant, ului de cres, tere, parcurs de la n către 1
j ← n;
while (j 6= 1) do
i ← T AT A[j];
if (rmin > rij ) then rmin ← rij ;
j ← i;

MĂRIRE FLUX : // se măres, te fluxul de-a lungul


// lant, ului de cres, tere, parcurs de la n către 1
j ← n;
while (j 6= 1) do
i ← T AT A[j];
if (cij > fij ) then
fij ← fij + rmin;
else
fji ← fji − rmin;
j ← i;

Teorema 2.7.2 (de corectitudine a Algoritmului Ford-Fulkerson).


În contextul Algoritmului 2.7.1, fie R = (G, s, t, c) ret, eaua dată, unde G =
(V, E). Presupunem că toate capacităt, ile arcelor ret, elei sunt numere ı̂ntregi,
adică
c(i, j) ∈ N, ∀(i, j) ∈ E.
TEMA 2. METODA GREEDY 74

Fie f0 fluxul init, ial. Presupunem că toate componentele fluxului f0 sunt
numere ı̂ntregi, adică

f0 (i, j) ∈ N, ∀(i, j) ∈ E,

de exemplu f0 = fluxul nul.


Fie µ1 , µ2 , . . . , µk lant, urile de cres, tere succesive obt, inute, k ≥ 0, s, i fie
f1 = f0 ⊕r0 (µ1 ), f2 = f1 ⊕r1 (µ2 ), . . . , fk = fk−1 ⊕rk−1 (µk ) fluxurile succesive
obt, inute, unde µ1 este lant, de cres, tere relativ la f0 , µ2 este lant, de cres, tere
relativ la f1 , . . . , µk este lant, de cres, tere relativ la fk−1 , s, i nu mai există
lant, uri de cres, tere relativ la fk . Atunci fk este un flux de valoare maximă ı̂n
ret, eaua R.
Mai mult, toate componentele fluxului fk s, i valoarea acestuia sunt numere
ı̂ntregi.
Demonstrat, ie. Conform Lemei 2.7.2, f1 , f2 , . . . , fk sunt fluxuri s, i v(f1 ) =
v(f0 ) + r0 (µ1 ), v(f2 ) = v(f1 ) + r1 (µ2 ) = v(f0 ) + r0 (µ1 ) + r1 (µ2 ), . . . , v(fk ) =
v(fk−1 ) + rk−1 (µk ) = v(f0 ) + r0 (µ1 ) + r1 (µ2 ) + · · · + rk−1 (µk ).
Deoarece toate capacităt, ie c(i, j), i, j ∈ V , s, i toate componentele f0 (i, j),
i, j ∈ V ale fluxului init, ial sunt numere ı̂ntregi, conform Definit, iei 2.7.7 s, i
Lemei 2.7.2 rezultă succesiv că

(r0 )µ1 (i, j) ∈ N∗ , ∀(i, j) ∈ E(µ1 ), r0 (µ1 ) ∈ N∗ ,


f1 (i, j) ∈ N, ∀i, j ∈ V, v(f1 ) ∈ N∗ ;
(r1 )µ2 (i, j) ∈ N∗ , ∀(i, j) ∈ E(µ2 ), r1 (µ2 ) ∈ N∗ ,
f2 (i, j) ∈ N, ∀i, j ∈ V, v(f2 ) ∈ N∗ ; . . . ,
(rk−1 )µk (i, j) ∈ N∗ , ∀(i, j) ∈ E(µk ), rk−1(µk ) ∈ N∗ ,
fk (i, j) ∈ N, ∀i, j ∈ V, v(fk ) ∈ N∗ . (2.7.5)

Deci

v(fk ) = v(f0 ) + r0 (µ1 ) + r1 (µ2 ) + · · · + rk−1 (µk ) ≥ v(f0 ) + k.

Evident, ({s}, V \ {s}) este o sect, iune ı̂n R având capacitatea


X
c({s}, V \ {s}) = c(s, j) ≤ (card (V ) − 1)cmax ,
j∈V \{s}

unde
cmax = max{c(i, j) | (i, j) ∈ E}
(capacitatea maximă a arcelor ret, elei). Conform Lemei 2.7.4 avem

v(fk ) ≤ c({s}, V \ {s}),


TEMA 2. METODA GREEDY 75

s, i astfel obt, inem


k ≤ (card (V ) − 1)cmax − v(f0 ),
deci numărul k de pas, i ai algoritmului (numărul de lant, uri de cres, tere suc-
cesive construite) este finit, adică există k ∈ N astfel ı̂ncât ret, eaua R nu
mai cont, ine lant, uri de cres, tere relativ la fluxul fk . Conform Teoremei 2.7.1
rezultă că fk este un flux de valoare maximă ı̂n R. Conform (2.7.5), toate
componentele fluxului fk s, i valoarea acestuia sunt numere ı̂ntregi.
Exemplul 2.7.10. Pentru ret, eaua R din Figura 2.7.1, aplicarea Algoritmului
Ford-Fulkerson este evident, iată ı̂n Figurile 2.7.5-2.7.10.

Figura 2.7.5:

Figura 2.7.6:
TEMA 2. METODA GREEDY 76

Figura 2.7.7:

Figura 2.7.8:

Figura 2.7.9:
TEMA 2. METODA GREEDY 77

Figura 2.7.10:

Lant, urile succesive de cres, tere relativ la fluxul curent sunt evident, iate
prin ı̂ngros, are, s, i anume:
µ1 = [1, 2, 3, 5, 6],
µ2 = [1, 2, 3, 6],
µ3 = [1, 4, 3, 6],
µ4 = [1, 4, 5, 3, 6],
µ5 = [1, 4, 5, 6].
Fluxul reprezentat ı̂n Figura 2.7.10 este de valoare maximă, deoarece nu mai
există lant, uri de cres, tere ı̂n R relativ la acest flux. Valoarea acestui flux este
11.
Pentru acest flux maxim, avem C-lant, uri de la nodul sursă s = 1 doar
la nodurile 1 s, i 4, aceste C-lant, uri sunt evident, iate prin ı̂ngros, are ı̂n Figura
2.7.10. Conform (2.7.4) rezultă că
(S, T ) = ({1, 4}, {2, 3, 5, 6})
este o sect, iune de capacitate minimă ı̂n R.
Observat, ia 2.7.10. Algoritmul Ford-Fulkerson este specific metodei de pro-
gramare Greedy. Pentru o ret, ea cu n noduri s, i m arce având toate ca-
pacităt, ile numere ı̂ntregi s, i pentru un flux init, ial având toate componentele
numere ı̂ntregi, de exemplu fluxul nul, conform demonstrat, iei Teoremei 2.7.2
rezultă că numărul de lant, uri de cres, tere necesare măririi succesive a flux-
ului init, ial, până se ajunge la un flux de valoare maximă, este de cel mult
(n − 1)cmax , unde cmax este capacitatea maximă a arcelor ret, elei. Pentru
fiecare flux curent, algoritmul necesită calculul reziduurilor celor m arce,
parcurgerea acestora pentru depistarea unui eventual lant, de cres, tere, deter-
minarea acestui lant, (de lungime cel mult m) s, i mărirea fluxului curent de-a
TEMA 2. METODA GREEDY 78

lungul lant, ului de cres, tere, operat, ii având complexitatea O (m). Rezultă că
Algoritmul Ford-Fulkerson are complexitatea O (mncmax ).
Observat, ia 2.7.11. Pentru o ret, ea având toate capacităt, ile numere rat, ionale,
putem aplica Algoritmul Ford-Fulkerson astfel:
• se ı̂nmult, esc toate capacităt, ile arcelor cu numitorul lor comun M,
obt, inându-se o ret, ea având toate capacităt, ile numere ı̂ntregi;
• se determină un flux de valoare maximă ı̂n această ret, ea, aplicând Algo-
ritmul Ford-Fulkerson (pentru un flux init, ial având toate componentele
numere ı̂ntregi, de exemplu fluxul nul);
• se ı̂mpart toate componentele acestui flux prin M, obt, inându-se un flux
de valoare maximă ı̂n ret, eaua init, ială.
Evident, toate componentele acestui flux maxim s, i valoarea lui sunt numere
rat, ionale.
Teorema 2.7.3 (Ford-Fulkerson). Fie R = (G, s, t, c) o ret, ea. Are loc
egalitatea
max{v(f ) | f = flux ı̂n R} = min{c(S, T ) | (S, T ) = sect, iune ı̂n R}
(adică ı̂n orice ret, ea valoarea maximă a unui flux este egală cu capacitatea
minimă a unei sect, iuni).
Demonstrat, ie. Fie G = (V, E) s, i V = {v1 , . . . , vn }, cu v1 = s s, i vn = t.
(f )
Pentru orice flux f ı̂n R, notăm cu X (f ) = (Xij )i,j=1,n ∈ Rn×n matricea
definită prin
(f )
Xij = f (vi , vj ), ∀i, j ∈ {1, . . . , n}.
Conform Definit, iei 2.7.2 avem
(f )
0 ≤ Xij ≤ Cij , ∀i, j ∈ {1, . . . , n},
n
X (f ) X n
(f )
Xji = Xij , ∀i ∈ {2, . . . , n − 1},
j=1 j=1

unde
Cij = c(vi , vj ), ∀i, j ∈ {1, . . . , n}.
Deci X (f ) ∈ D, unde
(
n×n

D= X ∈R 0 ≤ Xij ≤ Cij , ∀i, j ∈ {1, . . . , n},

n n
)
X X
Xji − Xij = 0, ∀i ∈ {2, . . . , n − 1} .
j=1 j=1
TEMA 2. METODA GREEDY 79

Avem D ⊆ Rn×n , D = 6 ∅ (deoarece 0n ∈ D).


Considerând funct, ia
n
X n
X
F : D → R, F (X) = Xin − Xni ,
i=1 i=1

avem v(f ) = F (X (f ) ).
Rezultă că un flux f ı̂n R este un flux de valoare maximă ı̂n R dacă s, i
numai dacă matricea X (f ) este un punct de maxim al funct, iei F (pe domeniul
D). F este o funct, ie reală de n2 variabile reale.
Cum F este o funct, ie continuă, iar mult, imea D este compactă (adică
ı̂nchisă s, i marginită), rezultă că F este mărginită s, i ı̂s, i atinge marginile, deci
există un punct de maxim X ∗ al funct, iei F (pe domeniul D).

Rezultă că fluxul f ∗ definit prin X (f ) = X ∗ , adică
f ∗ : V × V → R, f ∗ (vi , vj ) = Xij∗ , ∀i, j ∈ {1, . . . , n},
este un flux de valoare maximă ı̂n ret, eaua R.
Conform Teoremei 2.7.1 rezultă că nu există lant, uri de cres, tere ı̂n ret, eaua
R relativ la fluxul f ∗ . Fie
(
S ∗ = {i ∈ V | există C-lant, uri de la s la i ı̂n R relativ la f ∗ },
T ∗ = {i ∈ V | nu există C-lant, uri de la s la i ı̂n R relativ la f ∗ }.

Conform demonstrat, iei Teoremei 2.7.1 rezultă că (S ∗ , T ∗ ) este o sect, iune ı̂n
ret, eaua R s, i
v(f ∗ ) = c(S ∗ , T ∗ ),
deci conform Lemei 2.7.4 rezultă că (S ∗ , T ∗ ) este o sect, iune de capacitate
minimă ı̂n ret, eaua R. Astfel avem
max{v(f ) | f = flux ı̂n R} = v(f ∗ ) = c(S ∗ , T ∗ )
= min{c(S, T ) | (S, T ) = sect, iune ı̂n R}

Observat, ia 2.7.12. Conform demonstrat, iei teoremei anterioare, problema de-


terminării unui flux de valoare maximă ı̂ntr-o ret, ea dată este o problemă de
optimizare liniară:
n n
P P
X∈Rn×n i=1 it i=1 Xti
max X −
n n
P P
Xji − Xij = 0, ∀i ∈ {1, . . . , n} \ {s, t};
j=1 j=1

0 ≤ Xij ≤ Cij , ∀i, j ∈ {1, . . . , n}.
TEMA 2. METODA GREEDY 80

Deci această problemă poate fi rezolvată s, i prin algoritmii specifici optimizării


liniare, cum ar fi algoritmul simplex. Totus, i, datorită unor particularităt, i ale
problemei precum numărul mare de variabile s, i de restrict, ii sau alte restrict, ii
impuse fluxului (de exemplu condit, ia ca fluxurile să fie numere ı̂ntregi), uti-
lizarea algoritmilor specifici grafurilor este mai eficientă ı̂n rezolvarea prob-
lemei fluxului maxim.
Observat, ia 2.7.13. În termeni de optimizare matematică, not, iunea de sect, iune
este un concept dual pentru flux, iar problema sect, iunii de capacitate minimă
este o problemă duală pentru problema fluxului de valoare maximă. Lema
2.7.4 reprezintă dualitatea slabă, iat Teorema 2.7.3 reprezintă dualitatea tare
dintre cele două probleme.
Observat, ia 2.7.14. Din punct de vedere algoritmic, este important de sem-
nalat faptul că ı̂n orice ret, ea mult, imea sect, iunilor este finită (conform Ob-
servat, iei 2.7.6), spre deosebire de mult, imea fluxurilor, care, ı̂n general, este
infinită. Astfel capacitatea maximă a unei sect, iuni poate fi calculată prin
generarea tuturor sect, iunilor (algoritm ineficient!), dar nu putem genera toate
fluxurile.
Observat, ia 2.7.15. Pentru o ret, ea având s, i capacităt, i numere irat, ionale, Al-
goritmul Ford-Fulkerson poate să fie inoperabil, fiind posibil ca numărul de
pas, i ai algoritmului (numărul de lant, uri de cres, tere succesive construite) să
fie infinit, deoarece valorile reziduale ale lant, urilor de cres, tere succesive con-

P
struite pot forma o serie rk−1 (µk ) convergentă.
k=1
Totus, i, prin impunerea unor modalităt, i judicioase de construire a lant, uri-
lor de cres, tere succesive ı̂n cadrul Algoritmului Ford-Fulkerson, se obt, in algo-
ritmi care rezolvă problema fluxului maxim s, i ı̂n cazul capacităt, ilor irat, ionale.
Prezentăm ı̂n continuare un astfel de algoritm, bazat pe parcurgerea ı̂n lăt, ime
(BF) a grafului rezidual.
Algoritmul Edmonds-Karp este un algoritm ce rezolvă problema deter-
minării unui flux de valoare maximă s, i problema determinării unei sect, iuni
de capacitate minimă ı̂ntr-o ret, ea arbitrară, cu capacităt, i numere reale,
prin cres, terea succesivă a valorii fluxului curent de-a lungul unor lant, uri
de cres, tere, la fel ca ı̂n Algoritmul Ford-Fulkerson.
Algoritmul 2.7.2 (Edmonds-Karp). Fie R = (G, s, t, c) o ret, ea, unde G =
(V, E).
Algoritmul Edmonds-Karp are aceeas, i formă ca s, i Algoritmul Ford-Fulker-
son, această formă comună fiind descrisă detaliat ı̂n pseudocod ı̂n Algoritmul
2.7.1. Singura deosebire este că la fiecare pas se construies, te un lant, de
cres, tere (relativ la fluxul curent) de lungime minimă (bineı̂nt, eles, doar
dacă mai există lant, uri de cres, tere).
TEMA 2. METODA GREEDY 81

Acest lucru este realizat prin parcurgerea ı̂n lăt, ime (BF), pornind din
nodul sursă, a grafului rezidual relativ la fluxul curent.
Pentru a demonstra corectitudinea Algoritmului Edmonds-Karp, vom uti-
liza următoarea definit, ie.
Definit, ia 2.7.13. Fie f un flux ı̂n ret, eaua R = (G, s, t, c), unde G = (V, E).
Pentru orice două noduri i, j ∈ V notăm

min{l(µ) | µ = C-lant, de la i la j ı̂n R relativ la f }, dacă există

lf (i, j) = C-lant, uri de la i la j ı̂n R relativ la f ,


∞, ı̂n caz contrar,

unde l(µ) reprezintă lungimea lant, ului µ.


Lema 2.7.5. Fie f un flux ı̂n ret, eaua R = (G, s, t, c), unde G = (V, E). Fie
µ un lant, de cres, tere de lungime minimă ı̂n ret, eaua R relativ la fluxul f s, i
fie f ′ = f ⊕ r(µ) fluxul obt, inut prin mărirea fluxului f de-a lungul lant, ului
de cres, tere µ. Atunci au loc următoarele inegalităt, i:

lf ′ (s, i) ≥ lf (s, i), ∀i ∈ V, (2.7.6)


lf ′ (i, t) ≥ lf (i, t), ∀i ∈ V. (2.7.7)

Teorema 2.7.4 (de corectitudine a Algoritmului Edmonds-Karp).


În contextul Algoritmului 2.7.2, fie R = (G, s, t, c) ret, eaua dată, unde G =
(V, E) s, i c : E → R+ .
Fie f0 fluxul init, ial (de exemplu f0 = fluxul nul). Fie k numărul de pas, i ai
algoritmului (numărul de lant, uri de cres, tere succesive construite), k > 0. Fie
µ1 , µ2 , . . . , µk lant, urile de cres, tere succesive obt, inute, s, i fie f1 = f0 ⊕ r0 (µ1 ),
f2 = f1 ⊕ r1 (µ2 ), . . . , fk = fk−1 ⊕ rk−1(µk ) fluxurile succesive obt, inute,
unde µ1 este lant, de cres, tere de lungime minimă relativ la f0 , µ2 este lant,
de cres, tere de lungime minimă relativ la f1 , . . . , µk este lant, de cres, tere de
lungime minimă relativ la fk−1 , s, i nu mai există lant, uri de cres, tere relativ la
fk .
a) Numărul de pas, i ai algoritmului este finit s, i verifică inegalitatea
mn
k≤ ,
2
unde m = card (E) s, i n = card (V ).
b) fk este un flux de valoare maximă ı̂n ret, eaua R.
Exemplul 2.7.11. Pentru ret, eaua R din Figura 2.7.1, aplicarea Algoritmului
Edmonds-Karp este evident, iată ı̂n Figurile 2.7.11-2.7.15.
TEMA 2. METODA GREEDY 82

Figura 2.7.11:

Figura 2.7.12:

Figura 2.7.13:
TEMA 2. METODA GREEDY 83

Figura 2.7.14:

Figura 2.7.15:

Lant, urile succesive de cres, tere relativ la fluxul curent sunt evident, iate
prin ı̂ngros, are, s, i anume:

µ1 = [1, 2, 3, 6],
µ2 = [1, 4, 3, 6],
µ3 = [1, 4, 5, 6],
µ4 = [1, 4, 3, 5, 6].

Fluxul reprezentat ı̂n Figura 2.7.15 este de valoare maximă, deoarece nu mai
există lant, uri de cres, tere ı̂n R relativ la acest flux. Valoarea acestui flux este
11.
Pentru acest flux maxim, avem C-lant, uri de la nodul sursă s = 1 doar
la nodurile 1 s, i 4, aceste C-lant, uri sunt evident, iate prin ı̂ngros, are ı̂n Figura
TEMA 2. METODA GREEDY 84

2.7.15. Conform (2.7.4) rezultă că

(S, T ) = ({1, 4}, {2, 3, 5, 6})

este o sect, iune de capacitate minimă ı̂n R.


Observat, ia 2.7.16. Ca s, i Algoritmul Ford-Fulkerson, Algoritmul Edmonds-
Karp este tot un algoritm specific metodei de programare Greedy. Con-
form demonstrat, iei Teoremei 2.7.4, lant, urile de cres, tere succesive µ1 , µ2 ,
. . . , µk obt, inute prin aplicarea Algoritmului Edmonds-Karp au lungimile ı̂n
ordine crescătoare, adică

l(µ1 ) ≤ l(µ2 ) ≤ · · · ≤ l(µk ).

Pentru o ret, ea cu n noduri s, i m arce având toate capacităt, ile numere reale
s, i pentru un flux init, ial dat, de exemplu fluxul nul, conform Teoremei 2.7.4
rezultă că numărul de lant, uri de cres, tere necesare măririi succesive a fluxului
init, ial, până se ajunge la un flux de valoare maximă, este de cel mult mn 2
. Ca
s, i ı̂n cazul Algoritmului Ford-Fulkerson, pentru fiecare flux curent Algorit-
mul Edmonds-Karp necesită calculul reziduurilor celor m arce, parcurgerea
acestora (ı̂n lăt, ime) pentru depistarea unui eventual lant, de cres, tere, deter-
minarea acestui lant, (de lungime cel mult m) s, i mărirea fluxului curent de-a
lungul lant, ului de cres, tere, operat, ii având complexitatea O (m). Rezultă că
Algoritmul Edmonds-Karp are complexitatea O (m2 n).
Tema 3

Metoda Backtracking

3.1 Descrierea metodei. Algoritmi generali


Metoda Backtracking (metoda căutării cu revenire) se aplică proble-
melor a căror solut, ie se poate reprezenta sub forma unui vector

x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,

unde:

• S1 , S2 , . . . , Sn sunt mult, imi finite s, i nevide, elementele lor aflându-se


ı̂ntr-o relat, ie de ordine bine stabilită;

• ı̂ntre componentele x1 , x2 , . . . , xn ale vectorului x sunt precizate anu-


mite relat, ii, numite condit, ii interne.

Observat, ia 3.1.1. Pentru unele probleme, numărul de componente n al solu-


t, iilor nu este de la ı̂nceput cunoscut, el urmând a fi determinat pe parcurs.
De asemenea, pentru unele probleme, două solut, ii pot avea numere diferite
de componente.
Definit, ia 3.1.1. Mult, imea finită S = S1 × S2 × · · · × Sn se numes, te spat, iul
solut, iilor posibile.
Un vector x = (x1 , . . . , xn ) ∈ S se numes, te solut, ie posibilă.
Solut, iile posibile care satisfac condit, iile interne se numesc solut, ii rezul-
tat.
Observat, ia 3.1.2. Metoda Backtracking ı̂s, i propune să determine:

• fie o solut, ie rezultat,

• fie toate solut, iile rezultat.

85
TEMA 3. METODA BACKTRACKING 86

Obt, inerea tuturor solut, iilor rezultat poate constitui o etapă intermediară
ı̂n rezolvarea unei alte probleme, urmând ca, ı̂n continuare, dintre acestea să
fie alese solut, iile care optimizează (minimizează sau maximizează) o anumită
funct, ie obiectiv dată.
Observat, ia 3.1.3. O variantă de determinare a solut, iilor rezultat ar putea fi
următoarea metodă, numită metoda fort, ei brute:

• se generează succesiv toate solut, iile posibile, adică toate elementele pro-
dusului cartezian S1 × S2 × · · · × Sn ;

• pentru fiecare solut, ie posibilă se verifică dacă sunt satisfăcute condit, iile
interne;

• se ret, in cele care satisfac aceste condit, ii.

Această variantă are dezavantajul că timpul de execut, ie este foarte mare.
De exemplu, dacă card (Si ) = 2, i = 1, n, atunci spat, iul solut, iilor posibile
ar avea 2n elemente, iar complexitatea ar fi de ordinul Ω(2n ) (nesatisfăcătoa-
re!!).
Metoda Backtracking urmăres, te să evite generarea tuturor solut, iilor posibile,
ceea ce duce la scurtarea timpului de execut, ie.
Definit, ia 3.1.2. Fie k ∈ {1, . . . , n}. Un set de relat, ii definite pentru com-
ponenta xk ∈ Sk prin intermediul unor eventuale componente ale vectorului
(x1 , . . . , xk−1 ) ∈ S1 × S2 × · · · × Sk−1 repreintă condit, ii de continuare
pentru xk ı̂mpreună cu (x1 , . . . , xk−1 ) dacă:

1. aceste relat, ii sunt necesare pentru existent, a unei solut, ii rezultat de


forma
(x1 , . . . , xk−1 , xk , xk+1 , . . . , xn ),
adică neı̂ndeplinirea acestor condit, ii implică faptul că oricum am alege
xk+1 ∈ Sk+1 , . . . , xn ∈ Sn vectorul x = (x1 , . . . , xn ) nu poate fi o solut, ie
rezultat (nu verifică conditiile interne);

2. pentru k = n condit, iile de continuare coincid cu conditiile interne.

Orice vector (x1 , . . . , xk ) ∈ S1 ×S2 ×· · ·×Sk , cu 1 ≤ k ≤ n, care satisface


condit, iile de continuare, se numes, te solut, ie part, ială (solut, ie validă).
De asemenea, vectorul vid (fără elemente) este considerat ca fiind solut, ie
part, ială.
TEMA 3. METODA BACKTRACKING 87

Mecanismul metodei Backtracking


Prin metoda Backtracking solut, ia se construies, te pas cu pas (componentă cu
componentă) pe principiul stivei.

La fiecare nivel k, se caută un element din mult, imea de nivel Sk ,


care să fie atribuit componentei xk
s, i care ı̂mpreună cu (x1 , . . . , xk−1 ) să verifice condit, iile de continuare

Mai precis, avem următorii pas, i:

1. Se ı̂ncepe cu solut, ia part, ială dată de vectorul x vid.

2. Se ia primul element din mult, imea S1 s, i se atribuie lui x1 .

3. Presupunând generate elementele (x1 , x2 , . . . , xk−1 ), xi ∈ Si , i = 1, k − 1,


se avansează la nivelul k s, i se caută primul element disponibil din Sk
a cărui valoare să fie atribuită lui xk .
Avem următoarele cazuri:

3.1. A fost găsit ı̂n Sk un element disponibil v. Atunci:


– ı̂l atribuim lui xk ;
– se verifică dacă acesta ı̂mpreună cu elementele deja generate
x1 , . . . , xk−1 ı̂ndeplines, te condit, iile de continuare.
Avem următoarele subcazuri:
3.1.1. xk verifică condit, iile de continuare. Spunem că v este o
valoare validă pentru componenta xk .
Atunci:
– se extinde solut, ia part, ială la (x1 , . . . , xk−1 , xk );
– se verifică dacă k = n:
3.1.1.1. Dacă da, atunci s-a obt, inut o solut, ie rezultat.
TEMA 3. METODA BACKTRACKING 88

Acum, fie ne oprim, fie continuăm cu căutarea altei solut, ii


rezultat, reluând algoritmul (cu pasul 3.), considerând ge-
nerate (x1 , . . . , xk−1 ) s, i căutând ı̂n continuare pentru xk
un element netestat din Sk .
3.1.1.2. Dacă nu (k < n), se reia algoritmul cu pasul 3.,
căutând extinderea solut, iei part, iale (x1 , . . . , xk−1 , xk ) cu
testarea primului element din Sk+1 (se avansează).
3.1.2. xk nu verifică condit, iile de continuare. Atunci, oricum am
alege următoarele componente pentru x (adică pe xk+1 , . . . , xn ),
nu vom obt, ine o solut, ie rezultat. Prin urmare, se va relua al-
goritmul (cu pasul 3.), având generate x1 , . . . , xk−1 s, i căutând
extinderea solut, iei cu următorul element netestat din Sk (con-
tinuă căutarea).
3.2. Nu a fost găsit ı̂n Sk un element disponibil (netestat). Atunci se
consideră generate x1 , . . . , xk−2 (se revine) s, i se reia căutarea cu
următorul element din Sk−1 netestat, pentru extinderea solut, iei
part, iale (x1 , . . . , xk−2 ) (pas 3.).

Observat, ia 3.1.4. Algoritmul se termină atunci când nu mai există nici un


element din S1 netestat.
Observat, ia 3.1.5. După avansare, căutarea se va face ı̂ncepând cu testarea
primului element din mult, imea de nivel Sk corespunzătoare.
Observat, ia 3.1.6. După revenire, căutarea se va face ı̂ncepând cu următorul
element netestat (la etapele anterioare) din mult, imea de nivel Sk corespun-
zătoare.
Observat, ia 3.1.7. Condit, iile de continuare sunt necesare pentru existent, a
unei solut, ii rezultat, iar ideal este ca ele să fie s, i suficiente, ceea ce, de obicei,
este imposibil!
Alegerea acestor condit, ii este esent, ială ı̂n utilizarea metodei Bactracking,
deoarece cu cât condit, iile de continuare sunt mai restrictive, cu atât se limi-
tează mai mult numărul de căutări (ı̂n consecint, ă s, i numărul de avansări s, i
reveniri), deci metoda este mai eficientă.
De obicei condit, iile de continuare sunt restrict, iile condit, iilor interne la
primele k omponente.
Observat, ia 3.1.8. În general, problemele rezolvate cu Backtracking necesită
un timp foarte mare de execut, ie. De aceea, metoda se utilizează atunci când
nu avem la dispozit, ie un algoritm mai eficient. Problemele tipice care se pot
rezolva utilizând această metodă sunt cele nedeterminist-polinomial complete
(NP -complete).
TEMA 3. METODA BACKTRACKING 89

În continuare considerăm cazul particular ı̂n care mult, imile Sk , k =


1, n, cont, in termeni succesivi ai unor progresii aritmetice. Pentru fiecare k,
k = 1, n, mult, imea Sk va fi dată de:

• ak – primul termen al progresiei;

• rk > 0 – rat, ia progresiei;

• bk – ultimul termen al progresiei,

adică
Sk = {ak , ak + rk , ak + 2rk , . . . , bk }, ∀ k = 1, n.
Pentru acest caz particular, vom prezenta ı̂n continuare s, ase variante pen-
tru schema Backtracking: s, i anume două variante iterative s, i patru variante
recursive.
Algoritmul 3.1.1 (Schema Backtracking iterativă, varianta 1).
BACKTRACKING1 :
k ← 1;
x[1] ← a[1] − r[1];// pregătim introducerea valorii init, iale a1
// pentru x1
while k > 0 do
if x[k] < b[k] then
// mai există valori netestate pentru xk
x[k]
 ← x[k] + r[k];  // Căutare
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
if k = n then
// (x1 , . . . , xn ) este solut, ie rezultat
PRELUCREAZĂ(x[1], . . . , x[n]);
(*) // STOP, dacă se dores, te
// o singură solut, ie rezultat,
// sau k ← k − 1 (revenire fort, ată) dacă
// nu mai există valori valide pentru xn
else
k ← k + 1; // Avansare
x[k] ← a[k] − r[k]; // pregătim introducerea
// valorii init, iale ak pentru xk

else
// nu mai există valori netestate pentru xk
k ← k − 1; // Revenire
TEMA 3. METODA BACKTRACKING 90

Observat, ia 3.1.9. Dacă după determinarea s, i prelucrarea solut, iei rezultat nu


mai există valori valide pentru componenta x[n], atunci ı̂n loc de (∗) se poate
fort, a revenirea (k ← k − 1).
Următoarea schemă este echivalentă cu cea de mai sus.
Algoritmul 3.1.2 (Schema Backtracking iterativă, varianta 2).
BACKTRACKING2 :
k ← 1;
x[1] ← a[1] − r[1];// pregătim introducerea valorii init, iale a1
// pentru x1
while k > 0 do
if k ≤ n then
if x[k] < b[k] then
// mai există valori netestate pentru xk
 ← x[k] + r[k];
x[k] // Căutare
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
k ← k + 1; // Avansare
x[k] ← a[k] − r[k]; // pregătim introducerea
// valorii init, iale ak pentru xk
else
k ← k − 1; // Revenire
else
// (x1 , . . . , xn ) este solut, ie rezultat
PRELUCREAZĂ(x[1], . . . , x[n]);
(*) // STOP, dacă se dores, te
// o singură solut, ie rezultat
k ← k − 1; // Revenire, dacă se doresc
// toate solut, iile rezultat

Observat, ia 3.1.10. Schemele Backtracking de mai sus generează toate solut, iile
problemei date. Dacă se dores, te obt, inerea unei singure solut, ii, atunci ı̂n loc
de (∗) se poate insera o comandă de oprire (STOP).
Algoritmul 3.1.3 (Schema Backtracking recursivă, varianta 1).
TEMA 3. METODA BACKTRACKING 91

BACKR1(k) : // se generează (x[k], . . . , x[n])


x[k] ← a[k] − r[k]; // pregătim introducerea valorii init, iale
// a[k] pentru x[k]
while x[k] < b[k] do
 ← x[k] + r[k];
x[k]  // Căutare
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
if k = n then
// (x[1], . . . , x[n]) este solut, ie rezultat
PRELUCREAZĂ(x[1], . . . , x[n]);
else
BACKR1(k + 1); // Avansare, adică
// se generează, RECURSIV, (x[k + 1], . . . , x[n]).
// La ^ ıncheierea apelului BACKR1(k + 1) se produce
// revenirea la funct, ia BACKR1(k)

Apelare: BACKR1(1).
Următoarea schemă este echivalentă cu cea de mai sus.
Algoritmul 3.1.4 (Schema Backtracking recursivă, varianta 2).
BACKR2(k) :
if k ≤ n then
x[k] ← a[k] − r[k];
while x[k] < b[k] do
 ← x[k] + r[k];
x[k] 
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
BACKR2(k + 1);
else
PRELUCREAZĂ(x[1], . . . , x[n]);

Apelare: BACKR2(1).
Algoritmul 3.1.5 (Schema Backtracking recursivă, varianta 3).
TEMA 3. METODA BACKTRACKING 92

BACKR3(k) :
for v = a[k], b[k], r[k] do // Căutarea lui x[k] ^ ın mult, imea Sk
x[k]
 ← v; 
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
if k = n then
// (x[1], . . . , x[n]) este solut, ie rezultat
PRELUCREAZĂ(x[1], . . . , x[n]);
else
BACKR3(k + 1); // Avansare, adică
// se generează, RECURSIV, (x[k + 1], . . . , x[n]).
// La ^ ıncheierea apelului BACKR3(k + 1) se produce
// revenirea la funct, ia BACKR3(k)

Apelare: BACKR3(1).
Următoarea schemă este echivalentă cu cea de mai sus.
Algoritmul 3.1.6 (Schema Backtracking recursivă, varianta 4).
BACKR4(k) :
if k ≤ n then
for v = a[k], b[k], r[k] do
 ← v;
x[k] 
if (x[1], . . . , x[k]) verifică condit, iile de continuare then
BACKR4(k + 1);
else
PRELUCREAZĂ(x[1], . . . , x[n]);

Apelare: BACKR4(1).
Observat, ia 3.1.11. Schemele Backtracking din Algoritmii 3.1.1, 3.1.2, 3.1.3 s, i
3.1.4 pot fi usor adaptate s, i pentru situat, i ı̂n care elementele fiecărei mult, imi
Sk nu sunt ı̂n progresie aritmetică.
Observat, ia 3.1.12. În oricare din cele s, ase scheme de mai sus, verificarea
(validarea) condit, ilor de continuare

[(x[1], x[2], . . . , x[k]) verifică condit, iile de continuare]

se face adesea prin intermediul unei funct, ii VALID(x, k).


Observat, ia 3.1.13. Dacă, ı̂n oricare din cele s, ase scheme de mai sus, se renunt, ă
la testul

[(x[1], x[2], . . . , x[k]) verifică condit, iile de continuare],


TEMA 3. METODA BACKTRACKING 93

considerându-se astfel că orice solut, ie posibilă verifică condit, iile interne, a-
tunci se vor obt, ine ca solut, ii rezultat ale problemei toate elementele produsu-
lui cartezian S1 × S2 × · · · × Sn .

3.2 Colorarea grafurilor


Problema colorării grafurilor este următoarea:
Se consideră un graf neorientat fără bucle G = (V, E), cu mult, imea
nodurilor
V = {1, 2, . . . , n},
s, i un număr de m culori, numerotate cu 1, 2, . . . , m.
Se cere să se determine toate modalităt, ile de colorare ale nodurilor gra-
fului, utilizând cele m culori, astfel ı̂ncât oricare două noduri adiacente să fie
colorate cu culori diferite.

Modelarea problemei
Orice solut, ie a problemei se poate scrie sub forma

x = (x1 , x2 , . . . , xn ),

unde xi este culoarea atas, ată nodului i, xi ∈ {1, 2, . . . , m}.


Avem
x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,
unde
S1 = S2 = · · · = Sn = {1, 2, . . . , m}.
As, adar mult, imile Sk cont, in termenii succesivi ai unei progresii aritmetice,
ı̂n care 
 ak = 1,
rk = 1, ∀ k = 1, n.

bk = m,

Condit, iile interne:


Orice două noduri adiacente sunt colorate diferit, adică

xi 6= xj , ∀ [i, j] ∈ E.
TEMA 3. METODA BACKTRACKING 94

Condit, iile de continuare:


Dacă x1 , . . . , xk−1 sunt deja alese, atunci xk verifică condit, iile de continuare
(este valid ) dacă
xi 6= xk , ∀ i ∈ {1, . . . , k − 1} cu [i, k] ∈ E.
Altfel spus, xk nu verifică condit, iile de continuare (nu este valid ), dacă
există i ∈ {1, 2, . . . , k − 1} astfel ı̂ncât [i, k] ∈ E şi xi = xk .
Observat, ia 3.2.1. Pentru reprezentarea grafului utilizăm matricea de ad̄ia-
cent, ă
A = (aij )i,j=1,n .
Graful fiind neorientat, matricea de adiacent, ă este simetrică.
Obt, inem următorul algoritm Backtracking, descris ı̂n pseudocod, pentru
rezolvarea problemei.
Algoritmul 3.2.1.
COLORARE(A, n, m) :
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);
else
k ← k + 1;
x[k] ← 0;
else
k ← k − 1;

Funct, ia de verificare (validare) a condit, iilor de continuare este


VALID(x, k) :
for i = 1, k − 1 do
if (aik ≥ 1 and x[i] = x[k]) then
returnează 0;
returnează 1;

Aplicat, ie: colorarea hărt, ilor


Problema colorării hărt, ilor este următoarea:
TEMA 3. METODA BACKTRACKING 95

Se consideră o hartă s, i un număr de culori. Se cere să se coloreze fiecare


t, ară cu câte una din culori astfel ı̂ncât orice două t, ări ce au frontieră comună
să fie colorate diferit.

Modelarea problemei
Oricărei hărt, i i se poate asocia un graf neorientat simplu astfel:

• fiecărei t, ări ı̂i corespunde un nod;

• ı̂ntre două noduri există muchie dacă s, i numai dacă ele corespund unor
t, ări ce au frontieră comună.

O astfel de corespondent, ă este evident, iată ı̂n Figura 3.2.1.

2
1 2 1
4 5 3
4 3
5
6 6

Figura 3.2.1:

Astfel problema colorării unei hărt, i se reduce la problema colorării gra-


fului asociat.
Observat, ia 3.2.2. Graful asociat unei hărt, i este planar, adică există o repre-
zentare grafică ı̂n plan a acestuia astfel ı̂ncât muchiile să nu se intersecteze
decât ı̂n noduri.
Avem următorul rezultat celebru.
Teorema 3.2.1 (Teorema celor 4 culori). Pentru colorarea unui graf
planar sunt suficiente patru culori.
Observat, ia 3.2.3. Celebritatea problemei colorării hărt, ilor a constat ı̂n faptul
că ı̂n toate exemplele ı̂ntâlnite colorarea s-a putut face cu numai 4 culori, dar
teoretic se demonstrase că sunt suficiente 5 culori.
TEMA 3. METODA BACKTRACKING 96

• Problema a apărut ı̂n 1852, când un matematician amator, Fracis


Guthrie, a ı̂ncercat să coloreze harta comitatelor britanice, folosind
numai 4 culori.

• În anul 1976, Wolfgang Haken s, i Kenneth Appel, de la Universitatea


Illinois (SUA), au demonstrat că pentru colorare sunt suficiente 4 culori.

• Demonstrat, ia s-a efectuat cu ajutorul calculatorului electronic, anali-


zându-se 1482 configurat, ii ı̂n circa 1200 ore calculator.

3.3 Problema celor n dame pe tabla de s, ah


Problema celor n dame este următoarea:
Se consideră o tablă de s, ah de dimensiune n × n, n ≥ 2. Se cere să se
determine toate modalităt, ile de aranjare a n dame astfel ı̂ncât oricare două
dame să nu se atace reciproc (pe linii, coloane sau diagonale).
Observat, ia 3.3.1. Prin convent, ie, orice pătrăt, el al tablei este reprezentat prin
coordonatele sale (l, c), unde l reprezintă linia, iar c reprezintă coloana aces-
tuia. Liniile tablei sunt numerotate cu 1, 2, . . . , n de sus ı̂n jos, iar coloanele
sunt numerotate cu 1, 2, . . . , n de la stânga la dreapta.
Propozit, ia 3.3.1. Pe o tablă de dimensiune n × n nu putem as, eza mai mult
de n dame astfel ı̂ncât oricare două să nu se atace reciproc.
Demonstrat, ie. Oricum as, ezăm mai mult de n dame, cum tabla are n linii
rezultă că există cel put, in două dame as, ezate pe aceeas, i linie, s, i acestea se
atacă reciproc.

Modelarea problemei
În orice solut, ie rezultat, conform demonstrat, iei propozit, iei anterioare obt, inem
că pe fiecare linie a tablei se află exact o damă. Rezultă că orice solut, ie pentru
problema celor n dame se poate reprezenta sub forma unui vector

x = (x1 , x2 , . . . , xn ),

unde xi reprezintă coloana pe care se află dama de pe linia i, pentru i = 1, n.


De exemplu, pentru n = 5 o solut, ie rezultat este

x = (1, 3, 5, 2, 4),

corespunzătoare aranjării damelor din Figura 3.3.1.


TEMA 3. METODA BACKTRACKING 97

Figura 3.3.1:

Pentru cazul general, avem


x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,
unde
S1 = S2 = · · · = Sn = {1, 2, . . . , n}.
As, adar mult, imile Sk cont, in termenii succesivi ai unei progresii aritmetice,
ı̂n care 
 ak = 1,
rk = 1, ∀ k = 1, n.

bk = n,
Condit, iile interne:

• Damele de pe liniile i s, i j (i 6= j) nu se pot afla pe aceeas, i coloană:


xi 6= xj , ∀ i 6= j, i, j = 1, n;

• Damele de pe liniile i s, i j (i 6= j) nu se pot afla pe o aceeas, i diagonală:


|i−j| =
6 | xi − xj |, ∀ i 6= j, i, j = 1, n
sau, echivalent,
j − i 6= | xj − xi |, ∀ i, j a.ı̂. 1 ≤ i < j ≤ n.

Condit, iile de continuare:


Dacă avem solut, ia part, ială (x1 , . . . , xk−1 ), atunci xk verifică condit, iile de
continuare (este valid ) dacă
xk 6= xi s, i k − i 6= | xk − xi |, ∀ i = 1, k − 1.
TEMA 3. METODA BACKTRACKING 98

Altfel spus, dacă avem solut, ia part, ială x = (x1 , . . . , xk−1 ), atunci xk nu
verifică condit, iile de continuare (nu este valid ) dacă

∃ i ∈ {1, 2, . . . , k − 1} astfel ı̂ncât xk = xi sau k − i = | xk − xi |.

Obt, inem următorul algoritm Backtracking, descris ı̂n pseudocod, pentru


rezolvarea problemei.
Algoritmul 3.3.1.
DAME (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);
k ← k − 1; // fort, ăm revenirea, deoarece
// nu mai există valori valide pentru x[n]
else
k ← k + 1;
x[k] ← 0;
else
k ← k − 1;

Funct, ia de verificare (validare) a condit, iilor 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ă 0; // fals
returnează 1; // adevărat

Considerat, ii
• Pentru n = 2 problema nu are solut, ie, deoarece două dame as, ezate
pe linii s, i coloane diferite se află pe aceeas, i diagonală, deci se atacă
reciproc.

• Nici pentru n = 3 problema nu are solut, ie, deoarece orice două dame
as, ezate pe o aceeas, i culoare se atacă reciproc.
TEMA 3. METODA BACKTRACKING 99

• Pentru n ≥ 4 avem următorul rezultat celebru.

Teorema 3.3.1 (E. Pauls, 1874). Pentru orice n ≥ 4 problema celor n


dame are cel put, in o solut, ie.
Demonstrat, ie. Avem următoarele cazuri.
Cazul 1) n = 6k sau n = 6k + 4. Atunci o solut, ie este dată de as, ezarea
celor n dame ı̂n pătrăt, elele de coordonate (l, c) ce apart, in mult, imii
n no n n no
(2i, i) | 1 ≤ i ≤ ∪ (2i − 1, + i) | 1 ≤ i ≤ .
2 2 2
Cazul 2) n = 6k +1 sau n = 6k +5. Atunci o solut, ie este dată de as, ezarea
celor n dame ı̂n pătrăt, elele de coordonate (l, c) ce apart, in mult, imii
   
n−1 n+1 n−1
{(n, 1)}∪ (2i, i + 1) | 1 ≤ i ≤ ∪ (2i − 1, + i) | 1 ≤ i ≤ .
2 2 2

Cazul 3) n = 6k + 2. Atunci o solut, ie este dată de as, ezarea celor n dame


ı̂n pătrăt, elele de coordonate (l, c) ce apart, in mult, imii
n n n n n o
(4, 1), (n, − 1), (2, ), (n − 1, + 1), (1, + 2), (n − 3, n) ∪
2 n 2 2 2 o
n
∪ (n − 2i, i + 1) | 1 ≤ i ≤ − 3 ∪
n 2 o
n n
∪ (n − 2i − 3, + i + 2) | 1 ≤ i ≤ − 3 .
2 2
Cazul 4) n = 6k + 3. Atunci o solut, ie este dată de as, ezarea celor n dame
ı̂n pătrăt, elele de coordonate (l, c) ce apart, in mult, imii
 
n−1 n−1 n−1
(1, n), (5, 1), (n, − 1), (3, ), (n − 1, + 1) ∪
2 2 2
   
n−1 n−1
(2, + 2), (n − 3, n − 1) ∪ (n − 2i, i + 1) | 1 ≤ i ≤ −3 ∪
2 2
 
n−1 n−1
∪ (n − 2i − 3, + i + 2) | 1 ≤ i ≤ −3 ,
2 2

adică se as, ează o damă ı̂n colt, ul din dreapta sus (pătrăt, elul de coordonate
(1, n)) iar celelalte n − 1 dame se as, ează conform Cazului 3 ı̂n subtabla de
dimensiune (n − 1) × (n − 1) rămasă prin eliminarea primei linii s, i ultimei
coloane.
Conform Teoremei 3.3.1, Propozit, iei 3.3.1 s, i cazurilor n = 2 s, i n = 3
considerate mai sus obt, inem următorul rezultat.
TEMA 3. METODA BACKTRACKING 100

Corolarul 3.3.1. Numărul maxim de dame ce pot fi as, ezate pe o tablă de s, ah


de dimensiune n × n astfel ı̂ncât oricare două dame să nu se atace reciproc
este egal cu (
n − 1, dacă n ∈ {2, 3},
n, dacă n ≥ 4.

• Problema a fost expusă init, ial pentru tabla de s, ah obis, nuită 8 × 8 ı̂n
anul 1848 de către s, ahistul german Max Bezzel.

• Prima rezolvare a problemei celor 8 dame a fost publicată de către Franz


Nauck ı̂n anul 1850, care a găsit toate cele 92 de solut, ii ale problemei.
Acesta a propus s, i varianta generalizată la tabla de dimensiune n × n.

• Problema a fost imediat studiată de mult, i matematicieni, printre care


s, i celebrul matematician Carl Friedrich Gauss.

• Emil Pauls a fost primul care a demonstrat existent, a solut, iei pentru
orice n ≥ 4, ı̂n anul 1874, prin construct, ia din demonstrat, ia teoremei
de mai sus.

3.4 Problema nebunilor pe tabla de s, ah


Problema nebunilor este următoarea:
Se consideră o tablă de s, ah de dimensiune n × n, n ≥ 2. Se cere să
se determine toate modalităt, ile de aranjare a n − 1 nebuni pe pătrăt, ele de
aceeas, i culoare astfel ı̂ncât oricare doi nebuni să nu se atace reciproc (pe
diagonale).
Observat, ia 3.4.1. Utilizăm ı̂n continuare convent, ia din Observat, ia 3.3.1. Tot
prin convent, ie, pătrăt, elul situat ı̂n colt, ul din stânga sus al tablei, de coordo-
nate (1, 1), este colorat cu alb.
Propozit, ia 3.4.1. Pe o tablă de dimensiune n × n nu putem as, eza mai mult
de n − 1 nebuni pe pătrăt, ele de aceeas, i culoare astfel ı̂ncât oricare doi nebuni
să nu se atace reciproc.
Demonstrat, ie. Mult, imea N a pătrăt, elelor de culoare neagră poate fi partit, i-
onată ı̂n următoarele diagonale (cu direct, ia stânga-jos → dreapta-sus, ordo-
nate crescător după distant, a fat, ă de colt, ul din stânga-sus):

N = D1 ∪ D2 ∪ · · · ∪ Dn−1 , unde
Dk = {(l, c) | l + c = 2k + 1, 1 ≤ l ≤ n, 1 ≤ c ≤ n}, ∀k = 1, n − 1. (3.4.1)
TEMA 3. METODA BACKTRACKING 101

Rezultă că oricum as, ezăm mai mult de n − 1 nebuni pe pătrăt, ele de culoare
neagră există cel put, in doi nebuni as, ezat, i pe o aceeas, i diagonală Dk , s, i aces, tia
se atacă reciproc.
Pe de altă parte, mult, imea A a pătrăt, elelor de culoare albă poate fi parti-
t, ionată ı̂n următoarele diagonale (având, de asemenea, direct, ia stânga-jos →
dreapta-sus s, i ordonate crescător după distant, a fat, ă de colt, ul din stânga-sus):

A = D1 ∪ D2 ∪ · · · ∪ D n , unde
D k = {(l, c) | l + c = 2k, 1 ≤ l ≤ n, 1 ≤ c ≤ n}, ∀k = 1, n. (3.4.2)

Rezultă că oricum as, ezăm mai mult de n − 1 nebuni pe pătrăt, ele de culoare
albă, fie există cel put, in doi nebuni as, ezat, i pe o aceeas, i diagonală D k s, i aces, tia
se atacă reciproc, fie există câte cel put, in un nebun pe fiecare diagonală D k
s, i atunci nebunii de pe diagonalele D1 = {(1, 1)} s, i Dn = {(n, n)} se atacă
reciproc.

Modelarea problemei
Cazul 1) Considerăm cazul as, ezării celor n − 1 nebuni pe pătrăt, ele de culoare
neagră.
Pentru orice solut, ie rezultat, conform demonstrat, iei propozit, iei anterioare
obt, inem că pe fiecare din cele n − 1 diagonale Dk definite prin relat, ia (3.4.1)
se află exact un nebun.
Fiecare diagonală Dk , k = 1, n − 1. poate fi rescrisă 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}, dacă 1 ≤ k ≤
 ,
Dk = 2
hni

{(l, 2k + 1 − l) | 2k + 1 − n ≤ l ≤ n}, dacă <k ≤n−1
2
([t] reprezintă partea ı̂ntreagă a numărului t ∈ R).
Pentru orice k ∈ {1, 2, . . . , n − 1}, coloana pe care se află nebunul de pe
diagonala Dk este
c = 2k + 1 − l,
TEMA 3. METODA BACKTRACKING 102

deci este bine determinată de linia l a acestuia.


Rezultă că orice solut, ie se poate reprezenta sub forma unui vector
x = (x1 , x2 , . . . , xn−1 ),
unde xk reprezintă linia pe care se află nebunul de pe diagonala Dk , pentru
k = 1, n − 1.
De exemplu, pentru n = 5 o solut, ie rezultat este
x = (1, 4, 2, 5),
corespunzătoare aranjării nebunilor din Figura 3.4.1.

Figura 3.4.1:

Pentru cazul general, avem


x = (x1 , x2 , . . . , xn−1 ) ∈ S1 × S2 × · · · × Sn−1 ,
unde
 h i
{1, 2, . . . , 2k}, dacă 1 ≤ k ≤ n ,
Sk = 2 h i
{2k − n + 1, 2k − n + 2, . . . , n}, dacă n + 1 ≤ k ≤ n − 1.
2
As, adar mult, imile Sk cont, in termenii succesivi ai unei progresii aritmetice,
ı̂n care 
 ak = 1, hni
rk = 1, ∀ k = 1, ,
 2
bk = 2k,

 ak = 2k − n + 1, hni
rk = 1, ∀k = + 1, n − 1.
 2
bk = n,
TEMA 3. METODA BACKTRACKING 103

Condit, iile interne:


Pentru orice i 6= j, cei doi nebuni de pe diagonalele Di s, i Dj , as, ezat, i
deci pe liniile xi respectiv xj , s, i pe coloanele ci = 2i + 1 − xi respectiv
cj = 2j + 1 − xj , nu se pot afla nici pe o aceeas, i diagonală având direct, ia
stânga-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,

adică
xi − xj 6= i − j, ∀ i 6= j, i, j = 1, n − 1.
Condit, iile de continuare:
Dacă avem solut, ia part, ială (x1 , . . . , xk−1 ), atunci xk verifică condit, iile de
continuare (este valid ) dacă

xk − xi 6= k − i, ∀ i = 1, k − 1.

Altfel spus, dacă avem solut, ia part, ială x = (x1 , . . . , xk−1 ), atunci xk nu
verifică condit, iile de continuare (nu este valid ) dacă

∃ i ∈ {1, 2, . . . , k − 1} astfel ı̂ncât xk − xi = k − i.

Obt, inem următorul algoritm Backtracking, descris ı̂n pseudocod, pentru


rezolvarea problemei.
Algoritmul 3.4.1.
TEMA 3. METODA BACKTRACKING 104

NEBUNI1 (n) :
k ← 1;
x[1] ← 0;
ult ← 2; // ult este valoarea finală 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ătim introducerea valorii init, iale ak s, i
// actualizăm valoarea finală 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ăm valoarea finală bk pentru xk
n
if k ≤ then
2
ult ← 2k;
else
ult ← n;

Funct, ia de verificare (validare) a condit, iilor de continuare este


VALID1(x, k) :
for i = 1, k − 1 do
if x[k] − x[i] = k − i then
returnează 0; // fals
returnează 1; // adevărat
Cazul 2) Considerăm acum cazul as, ezării celor n − 1 nebuni pe pătrăt, ele
de culoare albă.
Pentru orice solut, ie rezultat, conform demonstrat, iei propozit, iei anterioare
obt, inem că un prim nebun se as, ează fie pe pătrăt, elul (1, 1) ce formează
TEMA 3. METODA BACKTRACKING 105

diagonala D 1 , fie pe pătrăt, elul (n, n) ce formează diagonala Dn , iar restul


de n − 2 nebuni se as, ează câte unul pe fiecare din diagonalele D2 , . . . , Dn−1
definite prin relat, ia (3.4.2).
Fiecare diagonală Dk , k = 2, n − 1. poate fi rescrisă astfel

Dk = {(l, c) | l + c = 2k, 1 ≤ l ≤ n, 1 ≤ c ≤ n}
= {(l, 2k − l) | 1 ≤ l ≤ n, 1 ≤ 2k − l ≤ n}
= {(l, 2k − l) | 1 ≤ l ≤ n, 2k − n ≤ l ≤ 2k − 1}
= {(l, 2k − l) | max{2k − n, 1} ≤ l ≤ min{2k − 1, n}},

deci
  
 n+1
{(l, 2k − l) | 1 ≤ l ≤ 2k − 1}, dacă 2 ≤ k ≤ ,


2
Dk =  

 n + 1
{(l, 2k − l) | 2k − n ≤ l ≤ n}, dacă
 < k ≤ n − 1.
2

Pentru orice k ∈ {2, . . . , n − 1}, coloana pe care se află nebunul de pe


diagonala D k este
c = 2k − l,
deci este bine determinată de linia l a acestuia.
Rezultă că orice solut, ie se poate reprezenta sub forma unui vector

y = (y1, y2 , . . . , yn−1),

unde
(
1, dacă primul nebun se află pe pătrăt, elul (1, 1),
y1 =
n, dacă primul nebun se află pe pătrăt, elul (n, n),

iar pentru k ∈ {2, . . . , n − 1} yk reprezintă linia pe care se află nebunul de


pe diagonala D k .
Avem
y = (y1 , y2 , . . . , yn−1 ) ∈ S1 × S2 × · · · × Sn−1 ,
unde


 {1, n}, dacă k = 1,  


 n+1
Sk = {1, 2, . . . , 2k − 1}, dacă 2 ≤ k ≤ 2
,
  

 n+1
{2k − n, 2k − n + 1, . . . , n}, dacă
 + 1 ≤ k ≤ n − 1.
2
TEMA 3. METODA BACKTRACKING 106

Pentru k ∈ {2, . . . , n − 1} mult, imile Sk cont, in termenii succesivi ai unei


progresii aritmetice, ı̂n care

 ak = 1, 
n+1

rk = 1, ∀ k = 2, ,
 2
bk = 2k − 1,

 ak = 2k − n, 
n+1

rk = 1, ∀k = + 1, n − 1.
 2
bk = n,
Condit, iile interne:
Analog cazului 1) obt, inem:

yi − yj 6= i − j, ∀ i 6= j, i, j = 2, n − 1.

În plus,
y1 ∈ {1, n} s, i yi 6= i, ∀ i = 2, n − 1
(nebunul de pe diagonala Di i = 2, n − 1, nu se poate afla pe diagonala dintre
pătrăt, elele (1, 1) s, i (n, n), deoarece s-ar ataca cu nebunul aflat pe unul din
aceste două pătrăt, elele).
Condit, iile de continuare:
Dacă avem solut, ia part, ială (y1 , . . . , yk−1 ), cu k ≥ 2, atunci yk verifică
condit, iile de continuare (este valid ) dacă

yk 6= k s, i yk − yi 6= k − i, ∀ i = 2, k − 1.

Altfel spus, dacă avem solut, ia part, ială (y1 , . . . , yk−1 ), cu k ≥ 2, atunci yk
nu verifică condit, iile de continuare (nu este valid ) dacă

yk = k sau ∃ i ∈ {2, . . . , k − 1} astfel ı̂ncât yk − yi = k − i.

Obt, inem următorul algoritm Backtracking, descris ı̂n pseudocod, pentru


rezolvarea problemei.
Algoritmul 3.4.2.
TEMA 3. METODA BACKTRACKING 107

NEBUNI2 (n) : // presupunem că n ≥ 3


k ← 2;
y[2] ← 0;
ult ← 3; // ult este valoarea finală 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ătrăt, elul (1, 1)
AFISARE(y);
y[1] ← n; // primul nebun pe pătrăt, elul (n, n)
AFISARE(y);
else
k ← k + 1;
// pregătim introducerea valorii init, iale ak s, i
// actualizăm valoarea finală 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ăm valoarea finală bk pentru yk
n+1
if k ≤ then
2
ult ← 2k − 1;
else
ult ← n;

Funct, ia de verificare (validare) a condit, iilor de continuare este


TEMA 3. METODA BACKTRACKING 108

VALID2(y, k) :
if y[k] = k then
returnează 0; // fals
for i = 2, k − 1 do
if y[k] − y[i] = k − i then
returnează 0; // fals
returnează 1; // adevărat

Considerat, ii
Teorema 3.4.1. Pentru orice n ≥ 2 problema nebunilor are cel put, in o
solut, ie.
Demonstrat, ie. Avem din nou următoarele două cazuri.
Cazul 1) Cei n − 1 nebuni trebuie as, ezat, i pe pătrăt, ele de culoare neagră.
Atunci o solut, ie este dată de as, ezarea celor n − 1 nebuni ı̂n pătrăt, elele de
coordonate (l, c) ce apart, in mult, imii
   
n−1 n−1
(1, 2i) | 1 ≤ i ≤ ∪ (n, 2i) | 1 ≤ i ≤ , dacă n este impar,
2 2
respectiv mult, imii
n no n no
(1, 2i) | 1 ≤ i ≤ ∪ (n, 2i − 1) | 2 ≤ i ≤ , dacă n este par.
2 2
Cazul 2) Cei n − 1 nebuni trebuie as, ezat, i pe pătrăt, ele de culoare albă.
Atunci o solut, ie este dată de as, ezarea celor n − 1 nebuni ı̂n pătrăt, elele de
coordonate (l, c) ce apart, in mult, imii
   
n+1 n−1
(1, 2i − 1) | 1 ≤ i ≤ ∪ (n, 2i − 1) | 2 ≤ i ≤ , dacă n este
2 2
impar, respectiv mult, imii
n no n no
(1, 2i − 1) | 1 ≤ i ≤ ∪ (n, 2i − 2) | 2 ≤ i ≤ , dacă n este par.
2 2

Conform Teoremei 3.4.1 s, i Propozit, iei 3.4.1 obt, inem următorul rezultat.
Corolarul 3.4.1. Numărul maxim de nebuni ce pot fi as, ezat, i pe pătrăt, ele de
aceeas, i culoare ale unei table de s, ah de dimensiune n × n, n ≥ 2, astfel ı̂ncât
oricare doi nebuni să nu se atace reciproc este egal cu n − 1.
TEMA 3. METODA BACKTRACKING 109

Evident, orice doi nebuni as, ezat, i pe pătrăt, ele de culori diferite nu se atacă
reciproc. Astfel, conform corolarului anterior obt, inem următorul rezultat.
Corolarul 3.4.2. Numărul maxim de nebuni ce pot fi as, ezat, i pe o tablă de
s, ah de dimensiune n × n, n ≥ 2, astfel ı̂ncât oricare doi nebuni să nu se
atace reciproc este egal cu 2n − 2.
Observat, ia 3.4.2. Pentru generarea tuturor modalităt, ilor de aranjare a 2n−2
nebuni pe o tablă de s, ah de dimensiune n × n astfel ı̂ncât oricare doi nebuni
să nu se atace reciproc putem proceda astfel:

• se generează toate modalităt, ile de as, ezare a n − 1 nebuni pe pătrăt, elele


de culoare albă astfel ı̂ncât oricare doi nebuni să nu se atace reciproc;

• pentru fiecare astfel de as, ezare, se generează toate modalităt, ile de


as, ezare a restului de n − 1 nebuni pe pătrăt, elele de culoare neagră
astfel ı̂ncât oricare doi din aces, tia să nu se atace reciproc.

Pentru aceasta putem utiliza funct, ia NEBUNI2 (n) din Algoritmul 3.4.2
ı̂n care ı̂nlocuim funct, ia AFISARE(y) cu funct, ia NEBUNI1 (n) din Algo-
ritmul 3.4.1.

3.5 Generarea obiectelor combinatoriale


3.5.1 Preliminarii
În continuare vom prezenta formule de numărare s, i algoritmi de generare
(enumerare) pentru cele mai cunoscute familii de obiecte combinatoriale:
produs cartezian, submult, imi, aranjamente (fără repetit, ie sau cu repetit, ie),
combinări (fără repetit, ie sau cu repetit, ie), permutări (fără repetit, ie sau cu
repetit, ie).
Reamintim pentru ı̂nceput câteva not, iuni uzuale.
Definit, ia 3.5.1. Fie A un alfabet (adică o mult, ime finită) s, i n ∈ N⋆ . O
secvent, ă de forma

a = a1 a2 . . . an , cu a1 , a2 , . . . , an ∈ A,

se numes, te cuvânt de lungime n peste alfabetul A. Lungimea cuvântului


a se notează cu |a|.
Observat, ia 3.5.1. Evident, cuvântul a1 a2 . . . an poate fi identificat cu vectorul
(a1 , a2 , . . . , an ).
TEMA 3. METODA BACKTRACKING 110

Definit, ia 3.5.2. Fie x ∈ R s, i n ∈ N. Notăm



 1, dacă n = 0,
[x]n = x(x − 1) . . . (x − n + 1), dacă n ≥ 1,
 | {z }
n factori

 1, dacă n = 0,
n x(x + 1) . . . (x + n − 1), dacă n ≥ 1.
[x] =
 | {z }
n factori

[x]n se numes, te polinomul factorial descrescător de gradul n, iar [x]n


se numes, te polinomul factorial crescător de gradul n.

3.5.2 Produs cartezian


Definit, ia 3.5.3. Produsul cartezian al mult, imilor A1 , A2 , . . . , An (n ∈
N⋆ ) este mult, imea

A1 × A2 × . . . × An = {(x1 , x2 , . . . , xn )|x1 ∈ A1 , x2 ∈ A2 , . . . , xn ∈ An }.

Exemplul 3.5.1. {a, b}×{+, −}×{c} = {(a, +, c), (a, −, c), (b, +, c), (b, −, c)}.
Propozit, ia 3.5.1 (de numărare a produsului cartezian). Fie n ∈ N⋆ s, i
A1 , A2 , . . . , An mult, imi finite. Atunci card (A1 × A2 × . . . × An ) = card (A1 ) ·
card (A2 ) · . . . · card (An ).
Demonstrat, ie. Se utilizează metoda induct, iei matematice după n.
Algoritmul 3.5.1 (de generare a produsului cartezian prin metoda
Backtracking). Fie mult, imile standard

A1 = {1, 2, . . . , m1 }, A2 = {1, 2, . . . , m2 }, . . . , An = {1, 2, . . . , mn }.

Vom utiliza metoda Backtracking. Avem

x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,

unde
S1 = A1 , S2 = A2 , · · · , Sn = An .
As, adar, mult, imile Sk , cont, in termeni succesivi ai unei progresii aritmeti-
ce, ı̂n care 
 ak = 1,
rk = 1, ∀ k = 1, n.

bk = mk ,
TEMA 3. METODA BACKTRACKING 111

Conform Observat, iei 3.1.13, eliminăm verificarea condit, iilor 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;

Funct, ia de afis, are este


AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];

Observat, ia 3.5.2. Pentru generarea produsului cartezian A1 × A2 × . . . × An


al unor mult, imi finite arbitrare
A1 = {a11 , a12 , . . . , a1m1 },
A2 = {a21 , a22 , . . . , a2m2 },
...,
An = {an1 , an2 , . . . , anmn }
se poate folosi algoritmul anterior, bazat pe generarea indicilor, ı̂nlocuind
afis, area indicilor xi cu afis, area elementelor corespunzătoare aixi din mult, imile
Ai , adică ı̂nlocuind funct, ia AFIS, ARE(x, n) cu funct, ia
AFISARE(x, a, n) :
for i = 1, n do
afis, ează a[i, x[i]];

3.5.3 Submult, imi


Propozit, ia 3.5.2 (de numărare a submult, imilor). Fie A o mult, ime
finită s, i P(A) mult, imea tuturor submult, imilor (părt, ilor) lui A. Atunci
card (P(A)) = 2card (A) .
TEMA 3. METODA BACKTRACKING 112

Demonstrat, ie. Fie A = {a1 , a2 , . . . , an }, n ∈ N⋆ . Notăm

{1, 2}n = {1, 2} × . . . × {1, 2} .


| {z }
de n ori

Definim funct, iile α : P(A) → {1, 2}n s, i β : {1, 2}n → P(A) prin:

1, dacă ai ∈ B,
• ∀B ∈ P(A), α(B) = (x1 , x2 , . . . , xn ), unde xi =
2, dacă ai 6∈ B;

• ∀(x1 , x2 , . . . , xn ) ∈ {1, 2}n, β(x1 , x2 , . . . , xn ) = {ai |xi = 1, i ∈ {1, . . . , n}}.

Funct, iile α s, i β sunt inverse una celeilalte, deci sunt bijective s, i

card (P(A)) = card ({1, 2}n ) = 2n .

Exemplul 3.5.2. Pentru A = {a, b, c}, corespondent, a submult, imi ↔ produs


cartezian din demonstrat, ia anterioară este redată ı̂n următorul tabel:
(x1 , x2 , x3 ) ∈ {1, 2}3 B ∈ P(A)
(1,1,1) {a, b, c}
(1,1,2) {a, b}
(1,2,1) {a, c}
(1,2,2) {a}
(2,1,1) {b, c}
(2,1,2) {b}
(2,2,1) {c}
(2,2,2) ∅

Deci A are 23 = 8 submult, imi.


Fie mult, imea A = {a1 , a2 , . . . , an }. Conform demonstrat, iei anterioare,
putem genera produsul cartezian {1, 2}n cu Algoritmul 3.5.1 ı̂nlocuind afis, a-
rea elementelor (x1 , . . . , xn ) cu afis, area submult, imilor corespunzătoare

B = {ai |xi = 1, i ∈ {1, . . . , n}}.

Obt, inem următorul algoritm descris ı̂n pseudocod.


Algoritmul 3.5.2 (de generare a submult, imilor, folosind metoda Back-
tracking).
TEMA 3. METODA BACKTRACKING 113

SUBMULT , IMI(a, n) :
k ← 1;
x[1] ← 0;
while k > 0 do
if x[k] < 2 then
x[k] ← x[k] + 1;
if k = n then
AFISARE(x, a, n);
else
k ← k + 1;
x[k] ← 0;
else
k ← k − 1;

Funct, ia de afis, are este


AFISARE(x, a, n) :
for i = 1, n do
if x[i] = 1 then afis, ează a[i];

3.5.4 Aranjamente cu repetit, ie


Propozit, ia 3.5.3 (de numărare a aranjamentelor cu repetit, ie). Fie
m, n ∈ N. Atunci numărul de cuvinte de lungime n peste un alfabet cu m
litere este egal cu mn .
Demonstrat, ie. Fie B = {1, 2, . . . , m} s, i C = {(x1 , x2 , . . . , xn )|xi ∈ B ∀ i}.
Cum C = B n , conform Propozit, iei 3.5.1 avem card (C) = mn .
Definit, ia 3.5.4. Cuvintele numărate ı̂n propozit, ia anterioară se numesc
aranjamente cu repetit, ie de m luate câte n. Prin abuz de limbaj, s, i
numărul lor, adică mn , se numes, te tot aranjamente cu repetit, ie de m
luate câte n.
Exemplul 3.5.3. Pentru m = 2 s, i n = 3, aranjamente cu repetit, ie sunt, ı̂n
ordine lexicografică:
(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2).
Deci avem 23 = 8 aranjamente cu repetit, ie.
Algoritmul 3.5.3 (de generare a aranjamentelor cu repetit, ie). Pen-
tru mult, imea standard B = {1, 2, . . . , m}, conform demonstrat, iei anterioare
putem genera produsul cartezian B n , cu Algoritmul 3.5.1 luând m1 = m2 =
· · · = mn = m.
TEMA 3. METODA BACKTRACKING 114

Observat, ia 3.5.3. Pentru o mult, ime A = {a1 , a2 , . . . , an } oarecare putem


genera indicii (x1 , . . . , xn ) cu algoritmul anterior s, i afis, a elementele cores-
punzătoare acestor indici (ax1 , . . . , axn ).

3.5.5 Aranjamente
Propozit, ia 3.5.4 (de numărare a aranjamentelor). Fie m, n ∈ N.
Atunci numărul de cuvinte de lungime n cu litere distincte peste un alfa-
bet cu m litere este egal cu [m]n .
Demonstrat, ie. Fie A = {1, 2, . . . , m} s, i

C1 = {(x1 , x2 , . . . , xn )|xi ∈ A ∀ i, xi 6= xj ∀ i 6= j}.

Avem
n
C1 = (x1 , x2 , . . . , xn )|x1 ∈ {1, . . . , m},
x2 ∈ {1, . . . , m} \ {x1 },
x3 ∈ {1, . . . , m} \ {x1 , x2 },
...,
o
xn ∈ {1, . . . , m} \ {x1 , . . . , xn−1 } ,

deci card (C1 ) = m(m − 1)(m − 2) . . . (m − n + 1) = [m]n .


Definit, ia 3.5.5. Cuvintele numărate ı̂n propozit, ia anterioară se numesc
aranjamente (fără repetit, ie) de m luate câte n. De asemenea s, i numărul
lor, adică [m]n , se numes, te tot aranjamente (fără repetit, ie) de m luate
câte n s, i se mai notează cu Anm .
Observat, ia 3.5.4. Pentru n > m avem

[m]n = m . . . (m − m) . . . (m − n + 1) = 0.

Exemplul 3.5.4. Pentru m = 4 s, i n = 2, aranjamentele sunt, ı̂n ordine lexi-


cografică:

(1, 2), (1, 3), (1, 4), (2, 1), (2, 3), (2, 4), (3, 1), (3, 2), (3, 4), (4, 1), (4, 2), (4, 3).

Deci avem [4]2 = 4 · 3 = 12 aranjamente.


TEMA 3. METODA BACKTRACKING 115

Algoritmul 3.5.4 (de generare a aranjamentelor prin metoda Back-


tracking, varianta 1). Fie mult, imea standard A = {1, 2, . . . , m} s, i n ≤ m.
Vom utiliza metoda Backtracking. Avem

x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,

unde
S1 = S2 = · · · = Sn = A.
As, adar, mult, imile Sk , cont, in termeni succesivi ai unei progresii aritmeti-
ce, ı̂n care 
 ak = 1,
rk = 1, ∀ k = 1, n.

bk = m,
Condit, iile interne:

xi 6= xj , ∀ i 6= j, i, j = 1, n.

Condit, iile de continuare:


Dacă avem solut, ia part, ială (x1 , . . . , xk−1 ), atunci xk verifică condit, iile de
continuare dacă
xk 6= xi , ∀ i = 1, k − 1.
Altfel spus, dacă avem solut, ia part, ială x = (x1 , . . . , xk−1 ), atunci xk nu
verifică condit, iile de continuare dacă

∃ i ∈ {1, 2, . . . , k − 1} astfel ı̂ncât 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;
TEMA 3. METODA BACKTRACKING 116

VALID(x, k) :
for i = 1, k − 1 do
if x[k] = x[i] then
returnează 0; // fals
returnează 1; // adevărat
Funct, ia de afis, are este, din nou:
AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];
Algoritmul 3.5.5 (de generare a aranjamentelor prin metoda Back-
tracking, varianta 2). Putem ı̂mbunătăt, i algoritmul anterior prin uti-
lizarea unui vector (y1 , y2 , . . . , ym ) cu semnificat, ia: dacă avem solut, ia part, ială
(x1 , . . . , xk−1 ), atunci
(
1, dacă i ∈ {x1 , . . . , xk−1 },
yi = ∀i = 1, m.
0, dacă i 6∈ {x1 , . . . , xk−1 },

Astfel xk verifică condit, iile de continuare dacă s, i numai dacă

yxk = 0.

Obt, inem următorul algoritm:


TEMA 3. METODA BACKTRACKING 117

ARANJAMENTE2(m, n) :
for i = 1, m do y[i] ← 0; // init, ial, solut, ia part, ială 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]] = 0 then // x[k] verifică condit, iile
// de continuare
if k = n then
AFISARE(x, n);
else
y[x[k]] ← 1; // ^
ınainte de avansare, se adaugă
// x[k] la solut, ia part, ială
k ← k + 1;
x[k] ← 0;
else
k ← k − 1;
y[x[k]] ← 0; // după revenire, se elimină
// x[k] din solut, ia part, ială

Funct, ia de afis, are este aceeas, i ca ı̂n algoritmul anterior.


Observat, ia 3.5.5. Pentru generarea aranjamentelor de m luate câte n ale unor
mult, imi finite arbitrare
A = {a1 , a2 , . . . , am }
se pot folosi algoritmii anteriori, bazat, i pe generarea indicilor, ı̂nlocuind
afis, area indicilor xi cu afis, area elementelor corespunzătoare axi din mult, imile
Ai , adică ı̂nlocuind funct, ia AFIS, ARE(x, n) cu funct, ia
AFISARE(x, a, n) :
for i = 1, n do
afis, ează a[x[i]];

3.5.6 Permutări
Propozit, ia 3.5.5 (de numărare a permutărilor). Fie n ∈ N. Atunci
numărul de cuvinte ce cont, in exact o dată fiecare literă a unui alfabet cu n
litere este egal cu n!, unde

n! = 1 · 2 · 3 · · · · · n (n factorial), 0! = 1.
TEMA 3. METODA BACKTRACKING 118

Demonstrat, ie. Luăm m = n ı̂n Propozit, ia 3.5.4 s, i folosim egalitatea [n]n =


n(n − 1) . . . 1 = n!.
Definit, ia 3.5.6. Cuvintele numărate ı̂n propozit, ia anterioară se numesc
permutări (fără repetit, ie) de ordinul n. De asemenea s, i numărul lor,
adică n!, se numes, te tot permutări (fără repetit, ie) de n.
Exemplul 3.5.5. Pentru n = 3, permutările mult, imii standard {1, 2, 3} sunt,
ı̂n ordine lexicografică:
(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1).
Deci avem 3! = 1 · 2 · 3 = 6 permutări.
Algoritmul 3.5.6 (de generare a permutărilor prin metoda Backtrack-
ing, varianta 1). Fie mult, imea standard A = {1, 2, . . . , n}. Luând m = n
ı̂n Algoritmul 3.5.4 de generare a aranjamentelor s, i fort, ând revenirea după
determinarea fiecărei permutări (deoarece după determinarea unei permutări
(x1 , x2 , . . . , xn ) nu mai există alte valori valide pentru componenta xn ) obt, i-
nem următorul algoritm.
PERMUTĂRI1(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, ăm revenirea, deoarece
// nu mai există valori valide pentru 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ă 0; // fals
returnează 1; // adevărat
TEMA 3. METODA BACKTRACKING 119

Funct, ia de afis, are este, din nou:


AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];
Algoritmul 3.5.7 (de generare a permutărilor prin metoda Backtrack-
ing, varianta 2). Luând m = n ı̂n Algoritmul 3.5.5 de generare a aranja-
mentelor s, i fort, ând din nou revenirea după determinarea fiecărei permutări
obt, inem următorul algoritm.
PERMUTĂRI2(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;

Funct, ia de afis, are este aceeas, i ca ı̂n algoritmul anterior.


Observat, ia 3.5.6. Pentru generarea permutărilor unei mult, imi arbitrare A =
{a1 , a2 , . . . , an } ı̂nlocuim afis, area indicilor (x1 , . . . , xn ) cu afis, area elementelor
corespunzătoare (ax1 , . . . , axn ).

3.5.7 Combinări
Propozit, ia 3.5.6 (de numărare a combinărilor). Fie m, n ∈ N. Atunci
numărul de cuvinte strict crescătoare de lungime n peste un alfabet (or-
donat) cu m litere
= numărul de submult, imi cu n elemente ale unei mult, imi cu m elemente
TEMA 3. METODA BACKTRACKING 120
 
[m]n def m
= = .
n! n
Demonstrat, ie. Fie A = {1, 2, . . . , m}. Notăm mult, imile din enunt, astfel:

C3 = {(c1 , c2 , . . . , cn )|ci ∈ A ∀ i, ci < ci+1 ∀ i}, S3 = {S|S ⊆ A, card (S) = n}.

Între aceste mult, imi definim funct, iile µ : C3 → S3 , ν : S3 → C3 prin:

• ∀ (c1 , c2 , . . . , cn ) ∈ C3 , µ(c1 , c2 , . . . , cn ) = {c1 , c2 , . . . , cn };

• ∀ {c1 , c2 , . . . , cn } ∈ S3 cu c1 < c2 < . . . < cn , ν({c1 , c2 , . . . , cn }) =


(c1 , c2 , . . . , cn ).

Aceste funct, ii sunt inverse una celeilalte, deci sunt bijective s, i astfel

card (C3 ) = card (S3 ).

Permutând fiecare combinare (c1 , c2 , . . . , cn ) ∈ C3 ı̂n toate cele n! mod-


uri posibile, obt, inem fără repetare toate aranjamentele din mult, imea C1 =
{(a1 , a2 , . . . , an )|ai ∈ A ∀ i, ai 6= aj ∀i 6= j}.
Deci card (C3 ) · n! = card (C1 ). Conform Propozit, iei 3.5.4, card (C1 ) = [m]n ,
[m]n
deci card (C3 ) = .
n!
Definit, ia 3.5.7. Oricare obiecte din cele 2 tipuri numărate ı̂n propozit, ia
anterioară se numesc combinări(fără repetit, ie) de m luate câte n. De
m
asemenea s, i numărul lor, adică , se numes, te tot combinări (fără
n
n
repetit, ie) de m luate câte n s, i se mai notează cu Cm .
 
m
Observat, ia 3.5.7. Pentru n > m avem = 0, deoarece [m]n = 0.
n
m!
Pentru n ≤ m, deoarece [m]n = m(m − 1) . . . (m − n + 1) = avem
  (m − n)!
m m!
= .
n n!(m − n)!
Exemplul 3.5.6. Pentru m = 5 s, i n = 3, corespondent, ele din demonstrat, ia
anterioară sunt redate ı̂n următorul tabel:
TEMA 3. METODA BACKTRACKING 121

(c1 , c2 , c3 ) ∈ C3 S ∈ S3
(1,2,3) {1, 2, 3}
(1,2,4) {1, 2, 4}
(1,2,5) {1, 2, 5}
(1,3,4) {1, 3, 4}
(1,3,5) {1, 3, 5}
(1,4,5) {1, 4, 5}
(2,3,4) {2, 3, 4}
(2,3,5) {2, 3, 5}
(2,4,5) {2, 4, 5}
(3,4,5) {3, 4, 5}.
 
5 [5]3 5·4·3
Deci avem = = = 10 combinări.
3 3! 1·2·3
Algoritmul 3.5.8 (de generare a combinărilor prin metoda Backtrack-
ing). Fie mult, imea standard A = {1, 2, . . . , m} s, i n ≤ m.
Vom utiliza metoda Backtracking. Fie solut, ia (combinarea)

x = (x1 , x2 , . . . , xn ).

Condit, iile interne:

1 ≤ x1 < x2 < · · · < xn−1 < xn ≤ m,

deci

xn ≤ m, xn−1 ≤ m − 1, xn−2 ≤ m − 2, . . . , x2 ≤ m − n + 2, x1 ≤ m − n + 1.

Astfel

x1 ∈ S1 = {1, 2, . . . , m − n + 1},
x2 ∈ S2 = {x1 + 1, x1 + 2, . . . , m − n + 2},
...
xk ∈ Sk = {xk−1 + 1, xk−1 + 2, . . . , m − n + k},
...
xn ∈ Sn = {xn−1 + 1, xn−1 + 2, . . . , m}.

As, adar, mult, imile Sk , cont, in termeni succesivi ai unei progresii aritmeti-
ce, ı̂n care 
 ak = xk−1 + 1,
rk = 1, ∀ k = 1, n,

bk = m − n + k,
TEMA 3. METODA BACKTRACKING 122

considerând x0 = 0.
Prin alegerea mult, imilor S1 , S2 , . . . , Sn am eliminat verificarea condit, iilor
de continuare.
COMBINĂRI(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;

Funct, ia de afis, are este, din nou:


AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];
Observat, ia 3.5.8. Analog Observat, iei 3.5.6, algoritmul anterior poate fi us, or
adaptat pentru generarea combinărilor pentru mult, imi oarecare.

3.5.8 Combinări cu repetit, ie


Propozit, ia 3.5.7 (de numărare a combinărilor cu repetit, ie). Fie
m, n ∈ N. Atunci numărul de cuvinte crescătoare  de
lungime n peste un
[m]n def m
alfabet (ordonat) cu m litere este egal cu = .
n! n
Demonstrat, ie. Fie B = {1, 2, . . . , m}, A = {1, 2, . . . , m + n − 1},

C4 = {(c1 , c2 , . . . , cn )|ci ∈ B ∀ i, ci ≤ ci+1 ∀ i}

C3 = {(d1 , d2 , . . . , dn )|di ∈ A ∀ i, di < di+1 ∀ i}.


Definim corespondent, ele ρ : C4 → C3 , σ : C3 → C4 astfel:

• ρ(c1 , c2 , c3 , . . . , cn ) = (c1 , c2 + 1, c3 + 2, . . . , cn + n − 1);

• σ(d1 , d2 , d3 , . . . , dn ) = (d1 , d2 − 1, d3 − 2, . . . , dn − n + 1).


TEMA 3. METODA BACKTRACKING 123

Acestea sunt funct, ii inverse,


 deci 
utilizând Propozitia 3.5.6 avem 
m+n−1 [m + n − 1]n [m]n m
card (C4 ) = card (C3 ) = = = = .
n n! n! n

Definit, ia 3.5.8. Cuvintele numărate ı̂n propozit, ia anterioară se numesc


combinări
  cu repetit, ie de m luate câte n. De asemenea s, i numărul lor,
m
adică , se numes, te tot combinări cu repetit, ie de m luate câte
n
n.
Exemplul 3.5.7. Pentru m = 3 s, i n = 4, combinările cu repetit, ie sunt, ı̂n
ordine lexicografică:
(1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 2, 2), (1, 1, 2, 3),
(1, 1, 3, 3), (1, 2, 2, 2), (1, 2, 2, 3), (1, 2, 3, 3), (1, 3, 3, 3),
(2, 2, 2, 2), (2, 2, 2, 3), (2, 2, 3, 3), (2, 3, 3, 3), (3, 3, 3, 3).
 
3 [3]4 3·4·5·6
Deci avem = = = 15 combinări cu repetit, ie.
4 4! 1·2·3·4
Algoritmul 3.5.9 (de generare a combinărilor cu repetit, ie prin metoda
Backtracking). Fie mult, imea standard A = {1, 2, . . . , m} s, i n ≥ 1.
Vom utiliza metoda Backtracking. Fie solut, ia (combinarea cu repetit, ie)
x = (x1 , x2 , . . . , xn ).
Condit, iile interne:
1 ≤ x1 ≤ x2 ≤ · · · ≤ xn−1 ≤ xn ≤ m.
Astfel
x1 ∈ S1 = {1, 2, . . . , m},
x2 ∈ S2 = {x1 , x1 + 1, . . . , m},
...
xk ∈ Sk = {xk−1 , xk−1 + 1, . . . , m},
...
xn ∈ Sn = {xn−1 , xn−1 + 1, . . . , m}.
As, adar, mult, imile Sk , cont, in termeni succesivi ai unei progresii aritmeti-
ce, ı̂n care 
 ak = xk−1 ,
rk = 1, ∀ k = 1, n,

bk = m,
TEMA 3. METODA BACKTRACKING 124

considerând x0 = 1.
Prin alegerea mult, imilor S1 , S2 , . . . , Sn am eliminat verificarea condit, iilor
de continuare.
COMBINĂRI 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;

Funct, ia de afis, are este, din nou:


AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];
Observat, ia 3.5.9. Analog Observat, iei 3.5.6, algoritmul anterior poate fi us, or
adaptat pentru generarea combinărilor cu repetit, ie pentru mult, imi oarecare.

3.5.9 Permutări cu repetit, ie


Propozit, ia 3.5.8 (de numărare a permutărilor cu repetit, ie). Fie
m, t1 , t2 , . . . , tm ∈ N s, i n = t1 + t2 + · · · + tm . Atunci numărul de cuvinte
de lungime n ce pot fi formate peste un alfabet cu m litere astfel ı̂ncât litera
numărul i să apară  de exact  ti ori pentru orice i ∈ {1, . . . , m} este egal cu
n! def n
= .
t1 !t2 ! . . . tm ! t1 , t2 , . . . , tm
Demonstrat, ie. Fie A = {1, 2, . . . , m} s, i

C5 = {(x1 , x2 , . . . , xn )|xi ∈ A ∀ i, card ({i|xi = j}) = tj ∀ j}.

Numărăm cuvintele din C5 astfel:


• 
alegem
 cei t1 indici (din totalul de n) ai literelor egale cu 1, rezultă
n
moduri posibile;
t1
TEMA 3. METODA BACKTRACKING 125

• pentru fiecare alegere de mai sus, alegem  cei t2 indici (din restul de
n − t1
n − t1 ) ai literelor egale cu 2, rezultă moduri posibile, deci
   t2
n n − t1
obt, inem moduri posibile de alegere a indicilor literelor
t1 t2
1 s, i 2;

• ...

• pentru fiecare alegere de mai sus, alegem cei tm indici (din restul de 
n − t1 − . . . − tm−1
n−t1 −. . .−tm−1 ) ai literelor egale cu m; rezultă
tm
moduri posibile, deci obt, inem
    
n n − t1 n − t1 − . . . − tm−1
...
t1 t2 tm

moduri posibile de alegere a tuturor indicilor literelor 1, 2, . . . , m.

Astfel
    
n n − t1 n − t1 − . . . − tm−1
card (C5 ) = ...
t1 t2 tm
n! (n − t1 )! (n − t1 − . . . − tm−1 )!
= · ·...·
t1 !(n − t1 )! t2 !(n − t1 − t2 )! tm !(n − t1 − . . . − tm )!
n!
=
t1 !t2 ! . . . tm !
(deoarece (n − t1 − . . . − tm )! = 0! = 1).
Definit, ia 3.5.9. Cuvintele numărate ı̂n propozit, ia anterioară se numesc
permutări cu repetit, ie (anagrame)
 de nluate câte t1 , t2 , . . . , tm . De
n
asemenea s, i numărul lor, adică , se numes, te tot permutări
t1 , t2 , . . . , tm
cu repetit, ie de n luate câte t1 , t2 , . . . , tm .
Observat
 , ia 3.5.10. Luând t1 = t2 = · · · = tm = 1 obt, inem n = m s, i
n
= n!, deci permutările (fără repetit, ie) sunt un caz particu-
1, 1, . . . , 1
lar
 al  permutărilor cu repetit, ie. Pe de altă parte, luând m = 2 obt, inem
n n!
= , deci s, i combinările (fără repetit, ie) sunt un caz particular
t1 , t2 t1 !t2 !
al permutărilor cu repetit, ie.
TEMA 3. METODA BACKTRACKING 126

Exemplul 3.5.8. Pentru m = 3 s, i t1 = 2, t2 = t3 = 1, deci n = 4, permutările


cu repetit, ie sunt, ı̂n ordine lexicografică:

(1, 1, 2, 3), (1, 1, 3, 2), (1, 2, 1, 3), (1, 2, 3, 1), (1, 3, 1, 2), (1, 3, 2, 1),

(2, 1, 1, 3), (2, 1, 3, 1), (2, 3, 1, 1), (3, 1, 1, 2), (3, 1, 2, 1), (3, 2, 1, 1).
 
4 4!
Deci avem = = 12 permutări cu repetit, ie.
2, 1, 1 2!1!1!
Algoritmul 3.5.10 (de generare a permutărilor cu repetit, ie prin meto-
da Backtracking, varianta 1). Fie mult, imea standard A = {1, 2, . . . , m},
t1 , t2 , . . . , tm ∈ N s, i n = t1 + t2 + · · · + tm .
Vom utiliza metoda Backtracking. Avem

x = (x1 , x2 , . . . , xn ) ∈ S1 × S2 × · · · × Sn ,

unde
S1 = S2 = · · · = Sn = A.
As, adar, mult, imile Sk , cont, in termeni succesivi ai unei progresii aritmeti-
ce, ı̂n care 
 ak = 1,
rk = 1, ∀ k = 1, n.

bk = m,
Condit, iile interne:

card ({i|i = 1, n, xi = j}) = tj ∀ j = 1, m.

Condit, iile de continuare:


Dacă avem solut, ia part, ială (x1 , . . . , xk−1 ), atunci xk verifică condit, iile de
continuare dacă

card ({i|i = 1, k − 1, xi = xk }) < txk .


TEMA 3. METODA BACKTRACKING 127

PERMUTĂRI CU REPETIT , IE1(n, t, m) :


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, ăm revenirea, deoarece
// nu mai există 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ă card ({i|i = 1, k − 1, x[i] = x[k]})
if p = 0 then returnează 0;
for i = 1, k − 1 do
if x[i] = x[k] then
q ← q + 1;
if q ≥ p then returnează 0;
returnează 1;
Funct, ia de afis, are este, din nou:
AFISARE(x, n) :
for i = 1, n do
afis, ează x[i];
Algoritmul 3.5.11 (de generare a permutărilor cu repetit, ie prin me-
toda Backtracking, varianta 2). Putem ı̂mbunătăt, i algoritmul anterior
prin utilizarea unui vector (y1, y2 , . . . , ym ) cu semnificat, ia: dacă avem solut, ia
part, ială (x1 , . . . , xk−1 ), atunci

yj = card ({i|i = 1, k − 1, xi = j}), ∀j = 1, m.


TEMA 3. METODA BACKTRACKING 128

Astfel xk verifică condit, iile de continuare dacă s, i numai dacă

yxk < txk .

Fort, ând din nou revenirea după determinarea fiecărei permutări cu repetit, ie,
obt, inem următorul algoritm.
PERMUTĂRI 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ă 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ă condit, iile
// de continuare
if k = n then
AFISARE(x, n);
k ← k − 1;
y[x[k]] ← y[x[k]] − 1; // după fort, area revenirii,
// se elimină x[k] din solut, ia part, ială
else
y[x[k]] ← y[x[k]] + 1; // ^ınainte de avansare, se
// adaugă x[k] la solut, ia part, ială
k ← k + 1;
x[k] ← 0;
else
k ← k − 1;
y[x[k]] ← y[x[k]] − 1; // după revenire, se elimină
// x[k] din solut, ia part, ială

Funct, ia de afis, are este aceeas, i ca ı̂n algoritmul anterior.


Observat, ia 3.5.11. Analog Observat, iei 3.5.6, algoritmul anterior poate fi us, or
adaptat pentru generarea permutărilor cu repetit, ie pentru mult, imi arbitrare.
Tema 4

Metoda Divide et Impera

4.1 Descrierea metodei. Algoritmi generali


Metoda Divide et Impera (”ı̂mparte s, i stăpânes, te”) este o metodă ge-
nerală de elaborare a algoritmilor care implică trei etape:

• Divide: Problema dată este ı̂mpărt, ită ı̂n două sau mai multe subpro-
bleme de acelas, i tip, dar de dimensiuni mai mici.

• Impera: Stăpânes, te subproblemele obt, inute. Subproblemele se re-


zolvă direct, dacă dimensiunea lor permite aceasta (cazuri elementare),
sau, fiind de acelas, i tip, se rezolvă ı̂n mod recursiv, prin acelas, i pro-
cedeu.

• Combină: Se combină solut, iile tuturor subproblemelor, pentru a obt, ine


solut, ia problemei init, iale.

În continuare prezentăm o schemă generală de lucru.


Algoritmul 4.1.1 (Metoda Divide et Impera).
Fie P (n) o problemă de dimensiune n ∈ N∗ . Presupunem că există n0 ∈

N , a ∈ N, a ≥ 1 s, i b ∈ R, b > 1 astfel ı̂ncât:

• ∀ n ∈ N∗ cu n ≤ n0 , rezolvarea problemei P (n) se poate face direct,


fără descompunere.
n
• ∀ n ∈ N∗ cu n > n0 , ∃ m1 , . . . , ma ∈ N∗ cu mi ≤ , ∀ i = 1, a,
b
astfel ı̂ncât rezolvarea problemei P (n) se poate face rezolvând succesiv
a subprobleme de acelas, i tip

P (m1 ), . . . , P (ma )

129
TEMA 4. METODA DIVIDE ET IMPERA 130

după care, combinând solut, iile celor a subprobleme, se obt, ine solut, ia
dorită a ı̂ntregii probleme P (n).
Algoritmul poate fi descris recursiv astfel:
DIVIMP(n, S) : // Rezolvarea problemei P (n)
if n ≤ n0 then
PRELUCREAZA(n, S); // Rezolvarea se face direct,
// rezult^ and solut, ia S a problemei P (n)
else
DESCOMPUNERE(n, a, m); // Se descompune problema,
// adică se determină m1 , . . . , ma
for i = 1, a do
DIVIMP(mi , si ); // Se obt, ine solut, ia si pentru
// subproblema P (mi )
COMBINA(s, a, S); // Se combină solut, iile s1 , . . . , sa ,
and solut, ia S a problemei P (n)
// rezult^

Observat, ia 4.1.1. Pentru orice i = 1, a avem


n
mi ≤ <n
b
(deoarece b > 1), adică subproblemele P (m1 ), . . . , P (ma ) au dimensiuni mai
mici decât problema mare P (n).
În continuare prezentăm o schemă particulară de lucru.
Algoritmul 4.1.2 (Metoda Divide et Impera, variantă vectorială).
Fie A = (a1 , a2 , . . . , an ), n ∈ N∗ , un vector asupra componentelor căruia
trebuie efectuată o prelucrare. Presupunem că există ε ∈ N astfel ı̂ncât:

• ∀ p, q ∈ {1, 2, . . . , n} cu q − p ≤ ε, prelucrarea secvent, ei (ap , . . . , aq ) se


poate face direct, fără descompunere.

• ∀ p, q ∈ {1, 2, . . . , n} cu q − p > ε, ∃ m ∈ {p, . . . , q − 1} astfel ı̂ncât


prelucrarea secvent, ei
(ap , . . . , aq )
se poate face prelucrând succesiv subsecvent, ele

(ap , . . . , am ) s, i
(am+1 , . . . , aq ),

după care, combinând rezultatele celor două prelucrări, se obt, ine pre-
lucrarea dorită a ı̂ntregii secvent, e (ap , . . . , aq ).
TEMA 4. METODA DIVIDE ET IMPERA 131

Algoritmul poate fi descris recursiv astfel:


DIVIMP(p, q, S) : // Prelucrarea secvent, ei (ap , . . . , aq )
if q − p ≤ ε then
PRELUCREAZA(p, q, S); // Prelucrarea se face direct,
// rezult^ and solut, ia S a secvent, ei (ap , . . . , aq )
else
DESCOMPUNERE(p, q, m); // Se descompune problema,
// adică se determină m
DIVIMP(p, m, S1); // Se obt, ine solut, ia S1 pentru
// subsecvent, a (ap , . . . , am )
DIVIMP(m + 1, q, S2); // Se obt, ine solut, ia S2 pentru
// subsecvent, a (am+1 , . . . , aq )
COMBINA(S1 , S2 , S); // Se combină solut, iile S1 s, i S2 ,
// rezult^ and solut, ia S a secvent, ei (ap , . . . , aq )

Procedura trebuie apelată prin:

DIVIMP(1, n, S).

În acest algoritm:

• ε reprezintă lungimea maximă a unei secvent, e (ap , . . . , aq ), notată pres-


curtat prin (p, q), pentru care prelucrarea se poate face direct, fără a
mai fi necesară ı̂mpărt, irea ı̂n subprobleme; procedura

PRELUCREAZA(p, q, S)

realizează prelucrarea secvent, elor de acest tip, furnizând rezultatul ı̂n


S.

• Procedura
COMBINA(S1 , S2 , S)
realizează combinarea rezultatelor S1 , S2 ale prelucrării celor două sub-
secvent, e vecine (p, m) s, i (m + 1, q), obt, inându-se rezultatul S al pre-
lucrării secvent, ei (p, q).

• Valoarea m este obt, inută apelând procedura

DESCOMPUNERE(p, q, m).
TEMA 4. METODA DIVIDE ET IMPERA 132

4.2 Problema turnurilor din Hanoi


Problema turnurilor din Hanoi este următoarea:
Se consideră trei tije notate cu 1, 2, 3 s, i n ≥ 1 discuri perforate de diametre
diferite. Init, ial, toate discurile se află pe tija 1, ı̂n ordinea crescătoare a
diametrelor, considerând sensul de la vârf către bază.
Se cere mutarea discurilor pe tija 2, ı̂n aceeas, i ordine, utilizând tija 3 s, i
respectând următoarele reguli:

• la fiecare pas se mută un singur disc;

• nu este permisă as, ezarea unui disc peste unul cu diametru mai mic.

Modelarea problemei
Vom nota o mutare cu perechea (i, j), ceea ce semnifică faptul că se mută un
disc de pe tija i pe tija j (i, j ∈ {1, 2, 3}).
Dacă n = 1, solut, ia directă este mutarea (1, 2).
Dacă n = 2, o solut, ie este formată din mutările (1, 3), (1, 2), (3, 2).
Dacă n > 2, problema se complică.
Notăm cu H(m, i, j) s, irul mutărilor necesare pentru a muta primele m
discuri de pe tija i pe tija j, folosind pentru manevre cealaltă tijă k := 6−i−j.
(Avem i + j + k = 1 + 2 + 3 = 6.)
Rezultă că, pentru problema noastră, avem de determinat s, irul H(n, 1, 2).
Avem

(i, j), dacă m = 1,
H(m, i, j) =
H(m − 1, i, k), (i, j), H(m − 1, k, j), dacă m ≥ 2.
TEMA 4. METODA DIVIDE ET IMPERA 133

As, adar, pentru m ≥ 2, mutarea a m discuri de pe tija i pe tija j este


echivalentă cu:
• mutarea a m − 1 discuri de pe tija i pe tija k = 6 − i − j, utilizând
pentru manevre tija j;

• mutarea discului rămas de pe tija i pe tija j;

• mutarea celor m − 1 discuri de pe tija k pe tija j, utilizând pentru


manevre tija i.
Deci rezolvarea unei probleme de dimensiune m ≥ 2 se reduce la rezolvarea
a trei probleme, de acelas, i tip, dar de dimensiuni mai mici:
• două de dimensiune m − 1, care se vor rezolva, recursiv, ı̂n acelas, i mod;

• una de dimensiune 1, care se rezolvă direct.


Obt, inem următorul algoritm Divide et Impera, descris ı̂n pseudocod, pentru
rezolvarea problemei.
Algoritmul 4.2.1.
HANOI(m, i, j) :
if m = 1 then
afis, ează(i, j); // se afis, ează mutarea (i, j)
else
k ← 6 − i − j;
HANOI(m − 1, i, k);
afis, ează(i, j); // se afis, ează mutarea (i, j)
HANOI(m − 1, k, j);
TEMA 4. METODA DIVIDE ET IMPERA 134

Procedura trebuie apelată prin:

HANOI(n, 1, 2).

Observat, ia 4.2.1. Pentru evaluarea complexităt, ii algoritmului anterior, no-


tăm cu M(n) numărul de mutări necesare (afis, ate). Avem


1, dacă n = 1,
M(n) =
M(n − 1) + 1 + M(n − 1), dacă n ≥ 2,

1, dacă n = 1,
=
2 · M(n − 1) + 1, dacă n ≥ 2.

Rescriind această relat, ie de recurent, ă sub forma

M(n) + 1 = 2(M(n − 1) + 1), ∀ n ≥ 2,

obt, inem că s, irul (M(n) + 1)n≥1 este o progresie geometrică având rat, ia 2 s, i
primul termen M(1) + 1 = 2, deci M(n) + 1 = 2n , ∀ n ≥ 1 s, i astfel se obt, ine
că
M(n) = 2n − 1, ∀ n ≥ 1.
Rezultă că timpul de execut, ie al algoritmului este

T (n) = Θ(2n ),

deci algoritmul este exponent, ial.


Propozit, ia 4.2.1. Orice algoritm care rezolvă problema turnurilor din Hanoi
necesită cel put, in 2n − 1 mutări.
Demonstrat, ie. Demonstrăm afirmat, ia din enunt, prin induct, ie după n ∈ N∗ .
Pentru n = 1, este evident că numărul de mutări necesare este de cel
put, in 1 = 21 − 1.
Presupunem afirmat, ia adevărată pentru n − 1 s, i o demonstrăm pentru
n, n ≥ 2. Într-adevăr, pentru orice rezolvare a problemei, sunt necesare el
put, in următoarele subetape:
• o mutare a discului n (cel mai mare) de pe tija 1 pe o altă tijă i;

• această mutare trebuie obligatoriu precedată de mutarea primelor n−1


discuri de pe tija 1 pe tija rămasă 6 − 1 − i, deci, conform ipotezei de
induct, ie sunt necesare cel put, in 2n−1 − 1 mutări;
• o mutare a discului n (cel mai mare) de pe o tijă j 6= 2 pe tija 2, mutare
ce poate să coincidă cu mutarea descrisă la prima subetapă;
TEMA 4. METODA DIVIDE ET IMPERA 135

• această mutare trebuie obligatoriu urmată de mutarea primelor n − 1


discuri de pe tija rămasă 6 − 2 − j pe tija 2 , deci, conform ipotezei de
induct, ie sunt necesare ı̂ncă cel put, in 2n−1 − 1 mutări.
Astfel numărul total de mutări necesare este de cel put, in

1 + 2(2n−1 − 1) = 2n − 1.

Următorul rezultat este o consecint, ă directă a Observat, iei 4.2.1 s, i propozit, ei


anterioare.
Propozit, ia 4.2.2. Algoritmul 4.2.1 este optim.

4.3 O problemă de acoperire


Considerăm următoarea problemă de acoperire:
Se consideră o suprafat, ă pătrată cu lungimea laturii n = 2k , k ≥ 1,
divizată ı̂n pătrate unitare, ca o tablă de s, ah. Unul dintre aceste pătrate
unitare este deja acoperit.
Se cere să se determine o acoperire a suprafet, ei rămase cu plăci de forma

constând din trei pătrate unitare.

Modelarea problemei
Memorăm suprafat, a pătrată ı̂ntr-o matrice S = (sij )i,j=1,n , fiecare pătrat
unitar fiind deci reprezentat de un element al acestei matrice.
Evident, o acoperire cu piese de forma dată utilizează un număr de
n2 − 1 4k − 1
=
3 3
piese.
n2 − 1
Considerăm că piesele sunt numerotate cu 1, 2, . . . , s, i că as, ezarea
3
piesei numărul i constă ı̂n completarea elementelor corespunzătoare
 din ma- 
n2 − 1
tricea S cu numărul i al piesei, pentru fiecare valoare i ∈ 1, 2, . . . , .
3
Pentru rezolvarea problemei utilizăm următoarea strategie Divide et Im-
pera:
TEMA 4. METODA DIVIDE ET IMPERA 136

• Se ı̂mparte suprafat, a pătrată ı̂n patru pătrate egale, formându-se patru


suprafet, e pătrate cu lungimea laturii 2k−1 .

• Una dintre cele patru suprafet, e are deja un pătrat unitar acoperit.

• Acoperim cu o placă trei pătrate unitare din centrul suprafet, ei mari ast-
fel ı̂ncât să acoperim câte un pătrat unitar s, i din celelalte trei suprafet, e.
Un exemplu ı̂n acest sens este redat ı̂n Figura 4.3.1.

Figura 4.3.1:

• Fiecare dintre cele patru suprafet, e este acum ı̂n condit, iile problemei,
deci pentru fiecare suprafat, ă se repetă procedeul de descompunere des-
cris anterior.

Obt, inem următorul algoritm Divide et Impera, descris ı̂n pseudocod, pen-
tru rezolvarea problemei.
Algoritmul 4.3.1.
TEMA 4. METODA DIVIDE ET IMPERA 137

ACOPERIRE(S, i, j, n, ip, jp) :


// S=matricea ce va fi completată cu numerele plăcilor
// (i, j)=colt, ul st^
anga sus
// n=lungimea laturii
// (ip, jp) = coordonatele pătratului unitar acoperit
if (n > 1) then
p ← p + 1; // numărul plăcii
m ← n/2; // noua dimensiune a laturii
// Coordonatele st^ anga sus ale celor 4 pătrate:
i1 ← i; j1 ← j;
i2 ← i; j2 ← j + m;
i3 ← i + m; j3 ← j;
i4 ← i + m; j4 ← j + m;
// Coordonatele pătratelor unitare ce vor fi acoperite
// ^ ın cele 4 pătrate:
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);

Apel: ACOPERIRE(S, 1, 1, n, ip, jp).


Tema 5

Metoda programării dinamice

5.1 Descrierea metodei. Algoritmi generali


Ca s, i metoda Divide et Impera, metoda programării dinamice implică
rezolvarea unei probleme prin descompunerea ı̂n subprobleme de acelas, i tip
de dimensiuni mai mici, dar de această dată subproblemele nu sunt disjuncte
(ca la metoda Divide et Impera), ci se pot suprapune, ı̂n sensul ca două
subprobleme pot avea (sub)subprobleme comune.
Solut, ia problemei se construies, te combinând solut, iile subproblemelor, nu-
mite s, i subsolut, ii (solut, ii part, iale).
Metoda se adresează problemelor de optimizare care ı̂ndeplinesc princi-
piul optimalităt, ii al lui Bellman: orice subsolut, ie a unei solut, ii optime
este la rândul ei o solut, ie optimă pentru subproblema corespondentă.
De regulă, subproblemele se rezolvă ı̂n ordinea crescătoare a dimensiu-
nii lor (strategia bottom-up), iar, pentru a evita repetarea procesului de
calcul necesar rezolvării aceleias, i subprobleme, solut, iile subproblemelor se
memorează temporar (de obicei ı̂n structuri de date de tip tablouri) pentru
reutilizări la posibile viitoare apeluri ale acestor subprobleme.
Solut, iile optime ale problemelor se exprimă ı̂n funct, ie de solut, iile optime
ale subproblemelor lor, de obicei prin intermediul unor relat, ii de recurent, ă,
s, i astfel determinarea solut, iilor optime revine la scrierea s, i rezolvarea acestor
relat, ii de recurent, ă.
Relat, iile de recurent, ă pot fi rezolvate s, i prin implementări recursive, ı̂n
care solut, ia optimă a problemei apelează solut, iile optime ale subproblemelor
(de dimensiuni mai mici, strategia top-down), dar ı̂n acest caz calculul
necesar rezolvării unei aceleias, i subprobleme poate fi reluat de foarte multe
ori prin apelarea repetată a acesteia, ceea ce conduce frecvent la un timp de
calcul exponent, ial.

138
TEMA 5. METODA PROGRAMĂRII DINAMICE 139

Deci este de preferat ca relat, iile de recurent, ă să fie rezolvate prin imple-
mentări nerecursive, utilizând strategia bottom-up, cu memorarea temporară
a solut, iilor optime ale subproblemelor.
Prezentăm o schemă generală de lucru:

• Problema dată se descompune ı̂n subprobleme de acelas, i tip, dar de


dimensiuni mai mici.

• Se alege o structură de date ı̂n care se memorează solut, iile optime ale
problemei s, i subproblemelor.

• Se determină relat, ia de recurent, ă ce caracterizează solut, ia optimă.

• Se rezolvă relat, ia de recurent, ă prin strategia bottom-up.

Observat, ia 5.1.1. Presupunem că solut, iile optime ale subproblemelor sunt
memorate ı̂ntr-un tablou

S = (S[i1 , . . . , ir ])(i1 ,...,ir )∈I1 ×···×Ir .

a) Dacă relat, ia de recurent, ă ce caracterizează solut, ia optimă exprimă


elementul S[i1 , . . . , ir ] ı̂n funct, ie de elemente următoare

S[j1 , . . . , jr ], (j1 , . . . , jr ) ≻ (i1 , . . . , ir )

(conform ordinii lexicografice), atunci calculul acestor elemente se face ı̂n


ordinea inversă, descrescătoare, a indicilor (i1 , . . . , ir ). Această abordare este
denumită s, i programare dinamică ı̂n varianta ı̂napoi.
b) Dacă relat, ia de recurent, ă ce caracterizează solut, ia optimă exprimă
elementul S[i1 , . . . , ir ] ı̂n funct, ie de elemente anterioare

S[j1 , . . . , jr ], (j1 , . . . , jr ) ≺ (i1 , . . . , ir )

(conform ordinii lexicografice), atunci calculul acestor elemente se face ı̂n


ordinea directă, crescătoare, a indicilor (i1 , . . . , ir ). Această abordare este
denumită s, i programare dinamică ı̂n varianta ı̂nainte.

5.2 Problema subs, irului crescător de lungime


maximă
Problema subs, irului crescător de lungime maximă este următoarea:
TEMA 5. METODA PROGRAMĂRII DINAMICE 140

Se consideră un s, ir de numere reale

a1 , a2 , . . . , an , n ≥ 1.

Se cere să se determine un subs, ir crescător de lungime maximă, adică un


subs, ir
ai1 ≤ ai2 ≤ · · · ≤ aik
(1 ≤ i1 < i2 < · · · < ik ≤ n) cu k= maxim.
Exemplul 5.2.1. De exemplu, pentru s, irul

10, 16, 2, 8, 4, 10, 3, 4, 9, 8

lungimea maximă a unui subs, ir crescător este egală cu 4 (nu există subs, iruri
crescătoare de lungime 5), iar un subs, ir crescător de lungime maximă este,
de exemplu,
2, 3, 4, 8.

Modelarea problemei

Metoda 1) Utilizăm programarea dinamică, varianta ı̂napoi. Considerăm


subproblemele constând ı̂n determinarea a câte unui subs, ir crescător de
lungime maximă care ı̂ncepe cu elementul ai , pentru orice i ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm doi vectori
L = (L[1], . . . , L[n]) s, i P = (P [1], . . . , P [n − 1]) având semnificat, ia

L[i] = lungimea maximă a unui subs, ir crescător care ı̂ncepe cu elementul ai ,


P [i] = indicele primului element care este succesor al lui ai ı̂ntr-un subs, ir
crescător de lungime maximă care ı̂ncepe cu ai , dacă există un astfel
de indice,
P [i] = −1, dacă nu există un astfel de indice,

pentru orice i ∈ {1, 2, . . . , n}.


Evident,
L[n] = 1
L[i] = max {1 + L[j] | ai ≤ aj }, dacă există un astfel de indice j,
j=i+1,n

L[i] = 1, dacă nu există un astfel de indice j,


P [i] = min {j | L[i] = 1 + L[j]}, dacă există un astfel de indice j,
j=i+1,n
TEMA 5. METODA PROGRAMĂRII DINAMICE 141

P [i] = −1, dacă nu există un astfel de indice j,


pentru orice i ∈ {1, 2, . . . , n − 1}.
Relat, ia de recurent, ă de mai sus exprimă elementul L[i] ı̂n funct, ie de
elementele următoare L[i + 1], . . . , L[n].
Rezolvarea relat, iei de recurent, ă a elementelor L[i] s, i calculul elementelor
P [i] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea inversă a indicilor, adică

i = n, n − 1, . . . , 2, 1.

O solut, ie a problemei este subs, irul

at1 ≤ at2 ≤ · · · ≤ atk


de lungime
k = max L[i],
i=1,n

construit astfel:
t1 = min {i | L[i] = k},
i=1,n

tj = P [tj−1 ], ∀j ∈ {2, . . . , k}.


Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂napoi,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.2.1.
TEMA 5. METODA PROGRAMĂRII DINAMICE 142

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 [tj−1];
for j = 1, k do
afis, ează atj ;
Exemplul 5.2.2. La aplicarea algoritmului anterior pentru s, irul din Exemplul
5.2.1 avem n = 10,
L[10] = 1;
L[9] = 1, P [9] = −1;
L[8] = 2, P [8] = 9;
L[7] = 3, P [7] = 8;
L[6] = 1, P [6] = −1;
L[5] = 3, P [5] = 8;
L[4] = 2, P [4] = 6;
L[3] = 4, P [3] = 5;
L[2] = 1, P [2] = −1;
L[1] = 2, P [1] = 2,
deci lungimea maximă a unui subs, ir crescător este
k=4
iar un subs, ir crescător de lungime maximă este dat de indicii
t1 = 3, t2 = P [t1 ] = 5, t3 = P [t2 ] = 8, t4 = P [t3 ] = 9,
TEMA 5. METODA PROGRAMĂRII DINAMICE 143

adică subs, irul


2, 4, 4, 9.
Observat, ia 5.2.1. Instruct, iunea
if(aj ≥ ai ) and (1 + L[j] > L[i])
se execută câte o dată pentru fiecare pereche de indici (i, j) cu i ∈ {n − 1, n −
n(n − 1)
2, . . . , 1} s, i j ∈ {i + 1, i + 2, . . . , n}, adică de 1 + 2 + · · · + n − 1 =
2
ori, deci algoritmul are complexitatea Θ(n2 ).
Observat, ia 5.2.2. Algoritmul anterior poate fi adaptat pentru determinarea
tuturor subs, irurilor crescătoare de lungime maximă. Pentru aceasta, păs-
trând semnificat, ia s, i construct, ia vectorului L, reconsiderăm semnificat, ia s, i
construct, ia vectorului P astfel:

P [i] = mult, imea indicilor tuturor elementelor care sunt succesori direct, i ai
lui ai ı̂ntr-un subs, ir crescător de lungime maximă care ı̂ncepe cu ai

(posibil vidă), pentru orice i ∈ {1, 2, . . . , n − 1}. Evident,

P [i] = {j = i + 1, n | L[i] = 1 + L[j]}, ∀ i ∈ {1, 2, . . . , n − 1}.

Orice solut, ie a problemei este un subs, ir de forma

at1 ≤ at2 ≤ · · · ≤ atk


de lungime
k = max L[i],
i=1,n

construit astfel:
t1 ∈ {i = 1, n | L[i] = k},
tj ∈ P [tj−1], ∀j ∈ {2, . . . , k}.
Pentru generarea tuturor acestor vectori (t1 , t2 , . . . , tk ) se poate utiliza metoda
Backtracking.
TEMA 5. METODA PROGRAMĂRII DINAMICE 144

De exemplu, pentru s, irul din Exemplul 5.2.1 avem

L[10] = 1;
L[9] = 1, P [9] = ∅;
L[8] = 2, P [8] = {9, 10};
L[7] = 3, P [7] = {8};
L[6] = 1, P [6] = ∅;
L[5] = 3, P [5] = {8};
L[4] = 2, P [4] = {6, 9, 10};
L[3] = 4, P [3] = {5, 7};
L[2] = 1, P [2] = ∅;
L[1] = 2, P [1] = {2, 6},

deci lungimea maximă a unui subs, ir crescător este k = 4 iar orice subs, ir
crescător de lungime maximă este dat de indicii

t1 ∈ {3}, t2 ∈ P [t1 ], t3 ∈ P [t2 ], t4 ∈ P [t3 ].

Obt, inem că subs, irurile crescătoare de lungime maximă 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 solut, ii (subs, iruri crescătoare de lungime maximă).


Metoda 2) Utilizăm programarea dinamică, varianta ı̂nainte. Considerăm
subproblemele constând ı̂n determinarea a câte unui subs, ir crescător de
lungime maximă care se ı̂ncheie cu elementul ai , pentru orice i ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm din nou doi vectori
L = (L[1], . . . , L[n]) s, i P = (P [2], . . . , P [n]) având acum semnificat, ia

L[i] = lungimea maximă a unui subs, ir crescător care se ı̂ncheie cu


elementul ai ,
P [i] = indicele primului element care este predecesor al lui ai ı̂ntr-un
subs, ir crescător de lungime maximă care se ı̂ncheie cu ai , dacă
există un astfel de indice,
P [i] = −1, dacă nu există un astfel de indice,

pentru orice i ∈ {1, 2, . . . , n}.


Evident,
L[1] = 1,
TEMA 5. METODA PROGRAMĂRII DINAMICE 145

L[i] = max {1 + L[j] | aj ≤ ai }, dacă există un astfel de indice j,


j=1,i−1

L[i] = 1, dacă nu există un astfel de indice j,


P [i] = min {j | L[i] = 1 + L[j]}, dacă există un astfel de indice j,
j=1,i−1

P [i] = −1, dacă nu există un astfel de indice j,


pentru orice i ∈ {2, 3, . . . , n}.
Relat, ia de recurent, ă de mai sus exprimă elementul L[i] ı̂n funct, ie de
elementele anterioare L[1], . . . , L[i − 1].
Rezolvarea relat, iei de recurent, ă a elementelor L[i] s, i calculul elementelor
P [i] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea directă a indicilor, adică

i = 1, 2, . . . , n − 1, n.

O solut, ie a problemei este subs, irul

at1 ≤ at2 ≤ · · · ≤ atk


de lungime
k = max L[i],
i=1,n

construit astfel:
tk = min {i | L[i] = k},
i=1,n

tj = P [tj+1], ∀j ∈ {k − 1, . . . , 1}.
Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂nainte,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.2.2.
TEMA 5. METODA PROGRAMĂRII DINAMICE 146

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]; // k = max{i = 1, n | L[i]}


m ← 1; // m = min{i = 1, n | L[i] = k}
for i = 2, n do
if (L[i] > k) then
k ← L[i];
m ← i;
tk ← m;
for j = k − 1, 1, −1 do
tj ← P [tj+1];
for j = 1, k do
afis, ează atj ;
Exemplul 5.2.3. La aplicarea algoritmului anterior pentru s, irul din Exemplul
5.2.1 avem n = 10,

L[1] = 1;
L[2] = 2, P [2] = −1;
L[3] = 1, P [3] = −1;
L[4] = 2, P [4] = 3;
L[5] = 2, P [5] = 3;
L[6] = 3, P [6] = 4;
L[7] = 2, P [7] = 3;
L[8] = 3, P [8] = 5;
L[9] = 4, P [9] = 8;
L[10] = 4, P [10] = 8,

deci lungimea maximă a unui subs, ir crescător este

k=4
TEMA 5. METODA PROGRAMĂRII DINAMICE 147

iar un subs, ir crescător de lungime maximă este at1 ≤ at2 ≤ · · · ≤ atk dat de
indicii
t4 = 9, t3 = P [t4 ] = 8, t2 = P [t3 ] = 5, t1 = P [t2 ] = 3,
adică subs, irul
2, 4, 4, 9.
Observat, ia 5.2.3. Analog algoritmului de la Metoda 1, s, i algoritmul anterior
are complexitatea Θ(n2 ).
Observat, ia 5.2.4. Printr-un procedeu similar celui descris ı̂n Observat, ia 5.2.2,
s, i algoritmul anterior poate fi adaptat pentru determinarea tuturor subs, iru-
rilor crescătoare de lungime maximă.

5.3 Problema drumurilor de sumă


maximă/minimă ı̂ntr-o matrice
Problema drumului de sumă maximă/minimă ı̂ntr-o matrice este
următoarea:
Se consideră o matrice de numere reale

A = (aij ) i = 1, m , m, n ∈ N∗ .
j = 1, n

Se cere ca dintre toate drumurile care ı̂ncep cu un element de pe prima


linie, coboară de fiecare dată pe verticală sau pe diagonală la un element
de pe linia următoare s, i se ı̂ncheie cu un element de pe ultima linie, să se
determine un drum pentru care suma elementelor parcurse este:
a) maximă;
b) minimă.
Exemplul 5.3.1. De exemplu, pentru matricea
 
40 30 10 35 20 25
 
 45 30 40 30 40 45 
 
 
 20 25 50 50 20 10 
A=  35 15 10 30 15 20 

 
 
 40 50 60 55 65 80 
 
40 20 15 20 10 10

un drum de sumă maximă este format din elementele ı̂ncadrate ı̂n cercuri,
având suma 240.
TEMA 5. METODA PROGRAMĂRII DINAMICE 148

Pentru aceeas, i matrice, un drum de sumă minimă este format din ele-
mentele ı̂ncadrate ı̂n pătrate, având suma 135.

Modelarea problemei
a) Considerăm problema drumului de sumă maximă.
Metoda 1) Utilizăm programarea dinamică, varianta ı̂napoi. Considerăm
subproblemele constând ı̂n determinarea a câte unui drum de sumă maximă
care ı̂ncepe cu elementul aij (s, i se ı̂ncheie cu un element de pe ultima linie),
pentru orice i ∈ {1, 2, . . . , m} s, i orice j ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm două matrice S =
(S[i, j]) i = 1, m s, i P = (P [i, j]) i = 1, m − 1 având semnificat, ia
j = 1, n j = 1, n

S[i, j] = suma maximă a unui drum de la aij la ultima linie,




 −1, dacă există un drum de sumă maximă de la aij la ultima



 linie având al doilea element pe ai+1,j−1 (adică prima



 coborâre are forma ւ),



 0, dacă există un drum de sumă maximă de la aij la ultima



 linie având al doilea element pe ai+1,j (adică prima


 coborâre are forma ↓) s, i nu există un drum de sumă
P [i, j] = maximă de la aij la ultima linie având al doilea element



 pe ai+1,j−1,



 1, dacă există un drum de sumă maximă de la aij la ultima



 linie având al doilea element pe ai+1,j+1 (adică prima



 coborâre are forma ց) s, i nu există un drum de sumă



 maximă de la aij la ultima linie având al doilea element

pe ai+1,j−1 sau pe ai+1,j .

Evident,
S[m, j] = amj , ∀ j ∈ {1, . . . , n}
s, i pentru orice i ∈ {1, . . . , m − 1} avem

S[i, 1] = ai1 + max{S[i + 1, 1], S[i + 1, 2]},


(
0, dacă S[i + 1, 1] ≥ S[i + 1, 2],
P [i, 1] =
1, dacă S[i + 1, 1] < S[i + 1, 2],
TEMA 5. METODA PROGRAMĂRII DINAMICE 149

S[i, j] = aij + max{S[i + 1, j − 1], S[i + 1, j], S[i + 1, j + 1]},


∀ j ∈ {2, . . . , n − 1}


 −1, dacă S[i + 1, j − 1] ≥ S[i + 1, j] s, i




 S[i + 1, j − 1] ≥ S[i + 1, j + 1],

 0, dacă S[i + 1, j] > S[i + 1, j − 1] si
,
P [i, j] =


 S[i + 1, j] ≥ S[i + 1, j + 1],



 1, dacă S[i + 1, j + 1] > S[i + 1, j − 1] s, i


S[i + 1, j + 1] > S[i + 1, j],
∀ j ∈ {2, . . . , n − 1}

S[i, n] = ain + max{S[i + 1, n − 1], S[i + 1, n]},


(
−1, dacă S[i + 1, n − 1] ≥ S[i + 1, n],
P [i, n] =
0, dacă S[i + 1, n − 1] < S[i + 1, n].

Relat, iile de recurent, ă de mai sus exprimă elementul S[i, j] ı̂n funct, ie de
elementele de pe linia următoare S[i + 1, j − 1], S[i + 1, j], S[i + 1, j + 1].
Rezolvarea relat, iei de recurent, ă a elementelor S[i, j] s, i calculul elementelor
P [i, j] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea inversă a liniilor, adică

i = m, m − 1, . . . , 2, 1.

O solut, ie a problemei este drumul

a1t1 , a2t2 , . . . , amtm


de sumă
M = max S[1, j],
j=1,n

construit astfel:
t1 = min {j | S[1, j] = M},
j=1,n

ti = ti−1 + P [i − 1, ti−1 ], ∀i ∈ {2, . . . , m}.


Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂napoi,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.3.1.
TEMA 5. METODA PROGRAMĂRII DINAMICE 150

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 ← ti−1 + P [i − 1, ti−1 ];
afis, ează M;
for i = 1, m do
afis, ează aiti ;
Exemplul 5.3.2. La aplicarea algoritmului anterior pentru matricea A din
Exemplul 5.3.1 avem
 
235 235 215 240 225 230
 195 195 205 195 205 180 
 
 145 150 165 165 135 120 
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  
P =  0 −1 1
 0 −1 0  .
 1 0 −1 1 1 0 
0 −1 −1 0 −1 −1
TEMA 5. METODA PROGRAMĂRII DINAMICE 151

Suma maximă are valoarea


M = max S[1, j] = 240.
j=1,6

Avem
t1 = min {j | S[1, j] = M} = 4,
j=1,6

t2 = t1 + P [1, t1 ] = 4 + P [1, 4] = 4 − 1 = 3,
t3 = t2 + P [2, t2 ] = 3 + P [2, 3] = 3 + 0 = 3,
t4 = t3 + P [3, t3 ] = 3 + P [3, 3] = 3 + 1 = 4,
t5 = t4 + P [4, t4 ] = 4 + P [4, 4] = 4 + 1 = 5,
t6 = t5 + P [5, t5 ] = 5 + P [5, 5] = 5 − 1 = 4,
deci drumul de sumă maximă produs de algoritm are elementele
a1t1 = a14 = 35, a2t2 = a23 = 40, a3t3 = a33 = 50,
a4t4 = a44 = 30, a5t5 = a55 = 65, a6t6 = a64 = 20.
Observat, ia 5.3.1. Pentru calculul fiecărui element al matricelor S s, i P sunt
necesare câte o atribuire s, i cel mult două comparat, ii, deci algoritmul are
complexitatea Θ(mn).
Observat, ia 5.3.2. Problema poate fi rezolvată s, i fără utilizarea matricei P .
În acest caz, pentru determinarea unui drum de sumă maximă ı̂nlocuim
instruct, iunea (∗) cu următoarea secvent, ă de instruct, iuni:
for i = 1, m − 1 do
if (ti > 1) and (S[i + 1, ti − 1] = S[i, ti ] − aiti ) then
ti+1 ← ti − 1; // cobor^ are de forma ւ
else
if S[i + 1, ti ] = S[i, ti ] − aiti then
ti+1 ← ti ; // cobor^ are de forma ↓
else
ti+1 ← ti + 1; // cobor^ are de forma ց

Observat, ia 5.3.3. Algoritmul 5.3.1 poate fi adaptat pentru determinarea tu-


turor drumurilor de sumă maximă. Pentru aceasta, păstrând semnificat, ia s, i
construct, ia matricei S, reconsiderăm semnificat, ia s, i construct, ia matricei P
astfel:
n
P [i, j] = k ∈ {−1, 0, 1} | există un drum de sumă maximă de la aij
o
la ultima linie având al doilea element pe ai+1,j+k ,
TEMA 5. METODA PROGRAMĂRII DINAMICE 152

pentru orice i ∈ {1, 2, . . . , m − 1} s, i orice j ∈ {1, 2, . . . , n} .


Evident, pentru orice i ∈ {1, 2, . . . , m − 1} avem
n o
P [i, 1] = k ∈ {0, 1} | ai+1,1+k = max{ai+1,1 , ai+1,2 } ,
n o
P [i, j] = k ∈ {−1, 0, 1} | ai+1,j+k = max{ai+1,j−1 , ai+1,j , ai+1,j+1} ,
∀ j ∈ {2, . . . , n − 1},
n o
P [i, n] = k ∈ {−1, 0} | ai+1,n+k = max{ai+1,n−1 , ai+1,n } .

Orice solut, ie a problemei este un drum de forma

a1t1 , a2t2 , . . . , amtm

de sumă
M = max S[1, j],
j=1,n

construit astfel:
t1 ∈ {j = 1, n | S[1, j] = M},
ti ∈ {ti−1 + k | k ∈ P [i − 1, ti−1 ]}, ∀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
 
235 235 215 240 225 230
 195 195 205 195 205 180 
 
 145 150 165 165 135 120 
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} 
 
P =  {0} {−1}
 {1} {0} {−1} {0}  .
 {1} {0} {−1} {1} {1} {0} 
{0} {−1} {−1, 1} {0} {−1} {−1, 0}
TEMA 5. METODA PROGRAMĂRII DINAMICE 153

Suma maximă are valoarea M = max S[1, j] = 240. Avem


j=1,6

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 sumă maximă 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 solut, ii (drumuri de sumă maximă).
Metoda 2) Utilizăm programarea dinamică, varianta ı̂nainte. Considerăm
subproblemele constând ı̂n determinarea a câte unui drum de sumă maximă
care se ı̂ncheie cu elementul aij (s, i se ı̂ncepe cu un element de pe prima linie),
pentru orice i ∈ {1, 2, . . . , m} s, i orice j ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm din nou două ma-
trice S = (S[i, j]) i = 1, m s, i P = (P [i, j]) i = 1, m − 1 având acum semnificat, ia
j = 1, n j = 1, n

S[i, j] = suma maximă a unui drum de la prima linie la aij ,




 1, dacă există un drum de sumă maximă de la prima



 linie la aij având penultimul element pe ai−1,j−1



 (adică ultima coborâre are forma ց),



 0, dacă există un drum de sumă maximă de la prima



 linie la aij având penultimul element pe ai−1,j


 (adică ultima coborâre are forma ↓) s, i nu există un
P [i − 1, j] = drum de sumă maximă de la prima linie la aij având



 penultimul element pe ai−1,j−1 ,



 −1, dacă există un drum de sumă maximă de la prima



 linie la aij având penultimul element pe ai−1,j+1



 (adică ultima coborâre are forma ւ) s, i nu există un



 drum de sumă maximă de la prima linie la aij având

penultimul element pe ai−1,j−1 sau pe ai−1,j .
TEMA 5. METODA PROGRAMĂRII DINAMICE 154

Evident,
S[1, j] = a1j , ∀ j ∈ {1, . . . , n}
s, i pentru orice i ∈ {2, . . . , m} avem

S[i, 1] = ai1 + max{S[i − 1, 1], S[i − 1, 2]},


(
0, dacă S[i − 1, 1] ≥ S[i − 1, 2],
P [i − 1, 1] =
−1, dacă 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}


 1, dacă S[i − 1, j − 1] ≥ S[i − 1, j] s, i




 S[i − 1, j − 1] ≥ S[i − 1, j + 1],

 0, dacă S[i − 1, j] > S[i − 1, j − 1] si
,
P [i − 1, j] =


 S[i − 1, j] ≥ S[i − 1, j + 1],



 −1, dacă S[i − 1, j + 1] > S[i − 1, j − 1] s, i


S[i − 1, j + 1] > S[i − 1, j],
∀ j ∈ {2, . . . , n − 1}

S[i, n] = ain + max{S[i − 1, n − 1], S[i − 1, n]},


(
1, dacă S[i − 1, n − 1] ≥ S[i − 1, n],
P [i − 1, n] =
0, dacă S[i − 1, n − 1] < S[i − 1, n].

Relat, iile de recurent, ă de mai sus exprimă elementul S[i, j] ı̂n funct, ie de
elementele de pe linia anterioară S[i − 1, j − 1], S[i − 1, j], S[i − 1, j + 1].
Rezolvarea relat, iei de recurent, ă a elementelor S[i, j] s, i calculul elementelor
P [i, j] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea directă a liniilor, adică

i = 1, 2, . . . , m − 1, m.

O solut, ie a problemei este drumul

a1t1 , a2t2 , . . . , amtm


de sumă
M = max S[m, j],
j=1,n
TEMA 5. METODA PROGRAMĂRII DINAMICE 155

construit astfel:
tm = min {j | S[m, j] = M},
j=1,n

ti = ti+1 − P [i, ti+1 ], ∀i ∈ {1, . . . , m − 1}.


Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂nainte,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.3.2.
DRUMMAX2(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 ];
afis, ează M;
for i = 1, m do
afis, ează aiti ;
Exemplul 5.3.3. La aplicarea algoritmului anterior pentru matricea A din
TEMA 5. METODA PROGRAMĂRII DINAMICE 156

Exemplul 5.3.1 avem


 
40 30 10
35 20 25

 85 70 75
65 75 70 

 105 110 125
125 95 85 
S= ,

 145 140 135
155 140 115 

 185 195 215
210 220 220 
235 235 230
240 230 230
 
0 1 −1 0 1 0

 0 1 0 1 0 1 

P =
 −1 −1 0 1 1 1 
.
 0 1 −1 0 1 1 
−1 −1 0 −1 0 1

Suma maximă are valoarea

M = max S[6, j] = 240.


j=1,6

Avem

t6 = min {j | S[6, j] = M} = 4,
j=1,6

t5 = t6 − P [5, t6 ] = 4 − P [5, 4] = 4 + 1 = 5,
t4 = t5 − P [4, t5 ] = 5 − P [4, 5] = 5 − 1 = 4,
t3 = t4 − P [3, t4 ] = 4 − P [3, 4] = 4 − 1 = 3,
t2 = t3 − P [2, t3 ] = 3 − P [2, 3] = 3 − 0 = 3,
t1 = t2 − P [1, t2 ] = 3 − P [1, 3] = 3 + 1 = 4,

deci drumul de sumă maximă produs de algoritm are elementele

a1t1 = a14 = 35, a2t2 = a23 = 40, a3t3 = a33 = 50,


a4t4 = a44 = 30, a5t5 = a55 = 65, a6t6 = a64 = 20.

Observat, ia 5.3.4. Analog algoritmului de la Metoda 1, s, i algoritmul anterior


are complexitatea Θ(mn).
Observat, ia 5.3.5. Problema poate fi rezolvată, din nou, s, i fără utilizarea
matricei P . În acest caz, pentru determinarea unui drum de sumă maximă
ı̂nlocuim instruct, iunea (∗) cu următoarea secvent, ă de instruct, iuni:
TEMA 5. METODA PROGRAMĂRII DINAMICE 157

for i = m, 2, −1 do
if (ti > 1) and (S[i − 1, ti − 1] = S[i, ti ] − aiti ) then
ti−1 ← ti − 1; // cobor^ are de forma ց
else
if S[i − 1, ti ] = S[i, ti ] − aiti then
ti−1 ← ti ; // cobor^ are de forma ↓
else
ti−1 ← ti + 1; // cobor^ are de forma ւ

Observat, ia 5.3.6. Analog Algoritmului 5.3.1, s, i Algoritmul 5.3.2 poate fi


adaptat pentru determinarea tuturor drumurilor de sumă maximă.

b) Considerăm problema drumului de sumă minimă.


Metoda 1) Utilizăm programarea dinamică, varianta ı̂napoi. Considerăm
subproblemele constând ı̂n determinarea a câte unui drum de sumă minimă
care ı̂ncepe cu elementul aij (s, i se ı̂ncheie cu un element de pe ultima linie),
pentru orice i ∈ {1, 2, . . . , m} s, i orice j ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm două matrice S =
(S[i, j]) i = 1, m s, i P = (P [i, j]) i = 1, m − 1 având semnificat, ia
j = 1, n j = 1, n

S[i, j] = suma minimă a unui drum de la aij la ultima linie,




 −1, dacă există un drum de sumă minimă de la aij la ultima



 linie având al doilea element pe ai+1,j−1 (adică prima



 coborâre are forma ւ),



 0, dacă există un drum de sumă minimă de la aij la ultima



 linie având al doilea element pe ai+1,j (adică prima


 coborâre are forma ↓) s, i nu există un drum de sumă
P [i, j] = minimă de la aij la ultima linie având al doilea element



 pe ai+1,j−1 ,



 1, dacă există un drum de sumă minimă de la aij la ultima



 linie având al doilea element pe ai+1,j+1 (adică prima



 coborâre are forma ց) s, i nu există un drum de sumă



 minimă de la aij la ultima linie având al doilea element

pe ai+1,j−1 sau pe ai+1,j .

Evident,
S[m, j] = amj , ∀ j ∈ {1, . . . , n}
TEMA 5. METODA PROGRAMĂRII DINAMICE 158

s, i pentru orice i ∈ {1, . . . , m − 1} avem

S[i, 1] = ai1 + min{S[i + 1, 1], S[i + 1, 2]},


(
0, dacă S[i + 1, 1] ≤ S[i + 1, 2],
P [i, 1] =
1, dacă S[i + 1, 1] > S[i + 1, 2],

S[i, j] = aij + min{S[i + 1, j − 1], S[i + 1, j], S[i + 1, j + 1]},


∀ j ∈ {2, . . . , n − 1}


−1, dacă S[i + 1, j − 1] ≤ S[i + 1, j] s, i




 S[i + 1, j − 1] ≤ S[i + 1, j + 1],

 0, dacă S[i + 1, j] < S[i + 1, j − 1] si
,
P [i, j] =


 S[i + 1, j] ≤ S[i + 1, j + 1],



 1, dacă S[i + 1, j + 1] < S[i + 1, j − 1] s, i


S[i + 1, j + 1] < S[i + 1, j],
∀ j ∈ {2, . . . , n − 1}

S[i, n] = ain + min{S[i + 1, n − 1], S[i + 1, n]},


(
−1, dacă S[i + 1, n − 1] ≤ S[i + 1, n],
P [i, n] =
0, dacă S[i + 1, n − 1] > S[i + 1, n].

Relat, iile de recurent, ă de mai sus exprimă elementul S[i, j] ı̂n funct, ie de
elementele de pe linia următoare S[i + 1, j − 1], S[i + 1, j], S[i + 1, j + 1].
Rezolvarea relat, iei de recurent, ă a elementelor S[i, j] s, i calculul elementelor
P [i, j] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea inversă a liniilor, adică

i = m, m − 1, . . . , 2, 1.

O solut, ie a problemei este drumul

a1t1 , a2t2 , . . . , amtm


de sumă
M = min S[1, j],
j=1,n

construit astfel:
t1 = min {j | S[1, j] = M},
j=1,n
TEMA 5. METODA PROGRAMĂRII DINAMICE 159

ti = ti−1 + P [i − 1, ti−1 ], ∀i ∈ {2, . . . , m}.


Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂napoi,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.3.3.
DRUMMIN1(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 ← ti−1 + P [i − 1, ti−1 ];
afis, ează M;
for i = 1, m do
afis, ează aiti ;
Exemplul 5.3.4. La aplicarea algoritmului anterior pentru matricea A din
Exemplul 5.3.1 avem
 
165 155 135 165 150 155
 140 125 140 130 130 135 
 
 95 100 125 125 100 90 
S=  ,
 95 75 75 95 80 95 

 60 65 75 65 75 90 
40 20 15 20 10 10
TEMA 5. METODA PROGRAMĂRII DINAMICE 160
 
1 0 −1 0 −1 −1

 0 −1 −1 1 1 0 

P =
 1 0 −1 −1 0 −1 .

 0 −1 −1 0 −1 −1 
1 1 0 1 0 −1
Suma minimă are valoarea

M = min S[1, j] = 135.


j=1,6

Avem

t1 = min {j | S[1, j] = M} = 3,
j=1,6

t2 = t1 + P [1, t1 ] = 3 + P [1, 3] = 3 − 1 = 2,
t3 = t2 + P [2, t2 ] = 2 + P [2, 2] = 2 − 1 = 1,
t4 = t3 + P [3, t3 ] = 1 + P [3, 1] = 1 + 1 = 2,
t5 = t4 + P [4, t4 ] = 2 + P [4, 2] = 2 − 1 = 1,
t6 = t5 + P [5, t5 ] = 1 + P [5, 1] = 1 + 1 = 2,

deci drumul de sumă minimă produs de algoritm are elementele

a1t1 = a13 = 10, a2t2 = a22 = 30, a3t3 = a31 = 20,


a4t4 = a42 = 15, a5t5 = a51 = 40, a6t6 = a62 = 20.

Observat, ia 5.3.7. Problema poate fi rezolvată s, i fără utilizarea matricei P .


În acest caz, pentru determinarea unui drum de sumă minimă ı̂nlocuim
instruct, iunea (∗) cu secvent, a de instruct, iuni din Observat, ia 5.3.2.
Metoda 2) Utilizăm programarea dinamică, varianta ı̂nainte. Considerăm
subproblemele constând ı̂n determinarea a câte unui drum de sumă minimă
care se ı̂ncheie cu elementul aij (s, i se ı̂ncepe cu un element de pe prima linie),
pentru orice i ∈ {1, 2, . . . , m} s, i orice j ∈ {1, 2, . . . , n}.
Pentru memorarea solut, iilor subproblemelor utilizăm din nou două ma-
TEMA 5. METODA PROGRAMĂRII DINAMICE 161

trice S = (S[i, j]) i = 1, m s, i P = (P [i, j]) i = 1, m − 1 având acum semnificat, ia


j = 1, n j = 1, n
S[i, j] = suma minimă a unui drum de la prima linie la aij ,


 1, dacă există un drum de sumă minimă de la prima



 linie la aij având penultimul element pe ai−1,j−1



 (adică ultima coborâre are forma ց),



 0, dacă există un drum de sumă minimă de la prima



 linie la aij având penultimul element pe ai−1,j


 (adică ultima coborâre are forma ↓) s, i nu există un
P [i − 1, j] = drum de sumă minimă de la prima linie la aij având



 penultimul element pe ai−1,j−1,



 −1, dacă există un drum de sumă minimă de la prima



 linie la aij având penultimul element pe ai−1,j+1



 (adică ultima coborâre are forma ւ) s, i nu există un



 drum de sumă minimă de la prima linie la aij având

penultimul element pe ai−1,j−1 sau pe ai−1,j .
Evident,
S[1, j] = a1j , ∀ j ∈ {1, . . . , n}
s, i pentru orice i ∈ {2, . . . , m} avem
S[i, 1] = ai1 + min{S[i − 1, 1], S[i − 1, 2]},
(
0, dacă S[i − 1, 1] ≤ S[i − 1, 2],
P [i − 1, 1] =
−1, dacă S[i − 1, 1] > S[i − 1, 2],

S[i, j] = aij + min{S[i − 1, j − 1], S[i − 1, j], S[i − 1, j + 1]},


∀ j ∈ {2, . . . , n − 1}


 1, dacă S[i − 1, j − 1] ≤ S[i − 1, j] s, i




 S[i − 1, j − 1] ≤ S[i − 1, j + 1],

 0, dacă S[i − 1, j] < S[i − 1, j − 1] si
,
P [i − 1, j] =


 S[i − 1, j] ≤ S[i − 1, j + 1],



 −1, dacă S[i − 1, j + 1] < S[i − 1, j − 1] s, i


S[i − 1, j + 1] < S[i − 1, j],
∀ j ∈ {2, . . . , n − 1}

S[i, n] = ain + min{S[i − 1, n − 1], S[i − 1, n]},


(
1, dacă S[i − 1, n − 1] ≤ S[i − 1, n],
P [i − 1, n] =
0, dacă S[i − 1, n − 1] > S[i − 1, n].
TEMA 5. METODA PROGRAMĂRII DINAMICE 162

Relat, iile de recurent, ă de mai sus exprimă elementul S[i, j] ı̂n funct, ie de
elementele de pe linia anterioară S[i − 1, j − 1], S[i − 1, j], S[i − 1, j + 1].
Rezolvarea relat, iei de recurent, ă a elementelor S[i, j] s, i calculul elementelor
P [i, j] conform strategiei bottom-up revine la calculul acestor elemente ı̂n or-
dinea directă a liniilor, adică

i = 1, 2, . . . , m − 1, m.

O solut, ie a problemei este drumul

a1t1 , a2t2 , . . . , amtm


de sumă
M = min S[m, j],
j=1,n

construit astfel:
tm = min {j | S[m, j] = M},
j=1,n

ti = ti+1 − P [i, ti+1 ], ∀i ∈ {1, . . . , m − 1}.


Obt, inem următorul algoritm de programare dinamică ı̂n varianta ı̂nainte,
descris ı̂n pseudocod, pentru rezolvarea problemei.
Algoritmul 5.3.4.
TEMA 5. METODA PROGRAMĂRII DINAMICE 163

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 ];
afis, ează M;
for i = 1, m do
afis, ează aiti ;
Exemplul 5.3.5. La aplicarea algoritmului anterior pentru matricea A din
Exemplul 5.3.1 avem
 
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  ,

 
 115 125 135 130 140 155 
155 135 140 150 140 150
 
−1 −1 0 1 0 1
 −1 0 1 0 1 1 
 
P = 0 1 1 −1 0 1  .
 −1 0 1 1 0 1 
0 1 1 0 1 1
TEMA 5. METODA PROGRAMĂRII DINAMICE 164

Suma minimă are valoarea

M = min S[6, j] = 135.


j=1,6

Avem

t6 = min {j | S[6, j] = M} = 2,
j=1,6

t5 = t6 − P [5, t6 ] = 2 − P [5, 2] = 2 − 1 = 1,
t4 = t5 − P [4, t5 ] = 1 − P [4, 1] = 1 + 1 = 2,
t3 = t4 − P [3, t4 ] = 2 − P [3, 2] = 2 − 1 = 1,
t2 = t3 − P [2, t3 ] = 1 − P [2, 1] = 1 + 1 = 2,
t1 = t2 − P [1, t2 ] = 2 − P [1, 2] = 2 + 1 = 3,

deci drumul de sumă minimă produs de algoritm are elementele

a1t1 = a13 = 10, a2t2 = a22 = 30, a3t3 = a31 = 20,


a4t4 = a42 = 15, a5t5 = a51 = 40, a6t6 = a62 = 20.

Observat, ia 5.3.8. Problema poate fi rezolvată, din nou, s, i fără utilizarea


matricei P . În acest caz, pentru determinarea unui drum de sumă minimă
ı̂nlocuim instruct, iunea (∗) cu secvent, a de instruct, iuni din Observat, ia 5.3.5.
Observat, ia 5.3.9. Analog Algoritmului 5.3.1, s, i Algoritmii 5.3.3 s, i 5.3.4 au
complexitatea Θ(mn).
De asemenea, ei pot fi adaptat, i pentru determinarea tuturor drumurilor
de sumă minimă.
Tema 6

Metoda Branch and Bound

165
Tema 7

Algoritmi euristici

166