Sunteți pe pagina 1din 9

Metoda Greedy

Consideraii teoretice
Explicarea numelui
n limba englez cuvntul greedy nseamn lacom. Algoritmii de tip greedy sunt algoritmi lacomi.
Ei vor s construiasc ntr-un mod ct mai rapid soluia problemei, fr a sta mult pe gnduri.
Algoritmii de tip greedy se caracterizeaz prin luarea unor decizii rapide care duc la gsirea
unei soluii a problemei. u ntotdeauna asemenea decizii rapide duc la o soluie optim, dar vom
vedea c e!ist anumite tipuri de probleme unde se pot obine soluii optime sau foarte apropiate de
optim.
Aplicabilitatea algoritmilor de tip Greedy
Algoritmii de tip "reedy se aplic la acele probleme unde datele de intrare sunt organizate sub
forma unei mulimi A #i se cere gsirea unei submulimi BA care s ndeplineasc anumite condiii
astfel nct s fie acceptat ca soluie posibil.
n general pot s e!iste mai multe submulimi BA care s reprezinte soluii posibile ale
problemei. $intre toate aceste submulimi B se pot selecta, conform unui anumit criteriu, anumite
submulimi B
*
care reprezint soluii optime ale problemei. %copul este de a gsi, dac este posibil,
una din mulimile B
*
. $ac acest lucru nu este posibil, atunci scopul este gsirea unei mulimi B
care s fie ct mai aproape de mulimile B
*
, conform criteriului de optimalitate impus.
Modul de lucru al algoritmilor de tip Greedy
&onstruirea mulimii B se face printr-un #ir de decizii. 'niial se porne#te cu mulimea vid (B = ).
*iecare decizie const n alegerea unui element din mulimea A, analiza lui #i eventual introducerea
lui n mulimea B. n funcie de modul n care se iau aceste decizii, mulimea B se va apropia mai
mult sau mai puin de soluia optim B
*
. n cazul ideal vom avea B = B
*
.
Algoritmii de tip greedy nu urmresc s determine toate soluiile posibile #i s aleag dintre
ele, conform criteriului de optimalitate impus, soluiile optime. $up cum spune #i numele,
algoritmii de tip greedy sunt caracterizai prin lcomie #i nu au rbdarea s investig+eze toate
variantele posibile de alegere a soluiei. Ei ncep construirea unei soluii pornind de la mulimea
vid, apoi lucreaz n pa#i, ntr-un mod ct se poate de +otrt, la fiecare pas se ia cte o decizie #i
se e!tinde soluia cu cte un element.
-a fiecare pas se analizeaz cte un element din mulimea A #i se decide dac s fie sau nu
inclus n mulimea B care se construie#te. Astfel se progreseaz de la cu un sir de mulimi
intermediare (, B
0
, B
1
, B
2
, ...), pn cnd se obine o soluie final B.
Implementare
&a #i sc+em general de lucru, e!ist dou variante de implementare a algoritmilor de tip "reedy.
.rima variant folose#te dou funcii caracteristice, alege #i posibil. alege este o funcie care
are rolul de a selecta urmtorul element din mulimea A care s fie prelucrat. *uncia posibil verific
dac un element poate fi adugat soluiei intermediare B
i
astfel nct noua soluie B
i+1
care s-ar
obine s fie o soluie valid. .rezentm n continuare pseudocodul pentru aceast prim variant
greedy. %e consider c numrul de elemente al mulimii A este n.

B = multimea vida
for (i=0; i<n; i++)
{
x = alege(A)
if (posibil(B,x))
* adauga elementul x la multimea B

$ificultatea la aceast prim variant const n scrierea funciei alege. $ac funcia alege este bine
conceput, atunci putem fi siguri c soluia B gsit este o soluie optim. $ac funcia alege nu este
foarte bine conceput, atunci soluia B gsit va fi doar o soluie posibil #i nu va fi optim. Ea se
poate apropia ns mai mult sau mai puin de soluia optim B
*
, n funcie de criteriul de selecie
implementat.
A doua variant de implementare difer de prima prin faptul c face o etap iniial de
prelucrare a mulimii A. .ractic se face o sortare a elementelor mulimii A, conform unui anumit
criteriu. $up sortare, elementele vor fi prelucrate direct n ordirea rezultat. .rezentm n
continuare pseudocodul pentru aceast a doua variant greedy.

B = multimea vida
prelu!rea"a(A)
for (i=0; i<n; i++)
{
x = A#i$
if (posibil(B,x))
* adauga elementul x la multimea B

-a a doua variant, dificultatea funciei alege nu a disprut, ci s-a transferat funciei prelucreaza.
$ac prelucrarea mulimii A este bine fcut, atunci se va a/unge n mod sigur la o soluie optim.
Altfel se va obine doar o soluie posibil, mai mult sau mai puin apropiat de optim.
Exemple
Problema comis-voiajorului
Enun %e condider n ora#e. %e cunosc distanele dintre oricare dou ora#e. 0n comis-voia/or
trebuie s treac prin toate cele n ora#e. %e cere s se determine un drum care porne#te dintr-un ora#,
trece e!act o dat prin fiecare din celelalte ora#e #i apoi revine la primul ora#, astfel nct lungimea
drumului s fie minim.
Reolvare .entru gsirea unei soluii optime la aceast problem este nevoie de algoritmi cu timp
de rulare foarte mare (de ordin e!ponenial 1(2
n
)). n situaiile practice asemenea algoritmi cu timp
foarte mare de rulare nu sunt acceptabili. &a urmare se face un compromis #i se accept algoritmi
care nu gsesc soluia optim ci doar o soluie aproape de optim, dar au n sc+imb un timp de rulare
mic. .ropunem n continuare o soluie greedy la aceast problem. 'deea este urmtoarea. %e
porne#te dintr-un ora# oarecare. %e caut drumul cel mai scurt care pleac din ora#ul respectiv ctre
ora#e nevizitate nc. %e parcurge acel drum #i se a/unge ntr-un alt ora#. Aici din nou se caut cel
mai scurt drum ctre ora#ele nevizitate nc. %e parcurge #i acest drum, a/ungndu-se ntr-un nou
ora#. 3epetnd ace#ti pa#i se parcurg toate ora#ele. -a final se parcurge drumul care duce napoi
spre primul ora#.
% considerm e!emplul din figura 4. Avem 5 ora#e cu distanele reprezentate n figur.
*igura 4, 3eea de ora#e pentru problema comis-voia/orului
.ornim vizitarea ora#elor din ora#ul 6. $e aici alegem drumul cel mai scurt ctre ora#ele nevizitate,
#i anume (6,2) de lungime 2. A/un#i n ora#ul 2, alegem din nou drumul cel mai scurt spre ora#ele
nevizitate, #i anume (2,7) de lungime 4. $in ora#ul 7 mai avem doar un singur ora# nevizitat, 4, a#a
c alegem drumul spre el (7,4) de lungime 4. n acest moment am parcurs toate ora#ele #i ne
rentoarcem n ora#ul 6 pe drumul (4,6) de lungime 5. $rumul rezultat este 6, 2, 7, 4, 6, iar distana
total de parcurs este 2 8 4 8 4 8 5 9 :.
Implementare $istanele ntre ora#e le memorm ntr-un tablou bidimensional D. $istana ntre
ora#ele (i,/) va fi memorat n elementul d
i,/
al matricii. n termeni "reedy, mulimea iniial A este
mulimea tuturor perec+ilor de ora#e. .entru reeaua de ora#e din figura 2 mulimea A conine
elementele ;(6,4), (6,2), (6,7), (4,2), (4,7), (2,7)<. =ulimea B care trebuie gsit va conine o parte
din aceste perec+i de ora#e, #i anume acele perec+i care nlnuite s formeze un drum ce trece prin
toate ora#ele. $ac avem un numr de n ora#e, atunci mulimea B va conine n perec+i de ora#e.
n implementare nu vom lucra cu mulimea A sub aceast form e!plicit de perec+i de
ora#e, ci vom folosi matricea distanelor D. $e asemenea drumul comis-voia/orului nu l vom pstra
sub form de perec+i de ora#e, ci sub forma unui sir al ora#elor.
.entru a memora drumul parcurs de comis-voia/or, folosim un tablou unidimensional drum.
n acest tablou vom memora indicii ora#elor parcuse, n ordinea parcurgerii.
.entru a #ti care ora#e au fost parcurse, facem o marcare logic a ora#elor folosind un tablou
unidimensional izitat. Elementele din acest tablou care au valoarea 4 reprezint ora#e vizitate.
Cod surs! n continuare este prezentat codul surs n limba/ul & care implementeaz algoritmul
descris mai sus.

%in!lude <stdio&'(
)* *umarul maxim de orase& *)
%define *+,A- .0
)* /onstanta !are se foloseste !a valoare
de initiali"are la !autarea minimului& *)
%define ,0*0, 10000
)* *umarul de orase& *)
int n;
)* ,atri!ea distantelor dintre orase& *)
int d#*+,A-$#*+,A-$;
)* 2rumul !omis voia3orului& /ontine
indi!ii oraselor in ordinea in !are
sunt ele par!urse& *)
int drum#*+,A-$;
)* 4e!tor !are memorea"a !are orase au
fost vi"itate& vi"itat#5$ va fi 1 da!a
orasul 5 a fost vi"itat, 0 altfel& *)
int vi"itat#*+,A-$;
)* 6un!tie !are alege urmatorul element !are
sa fie prelu!rat din multimea oraselor&
7rimeste !a parametru ultimul oras !are
a fost vi"itat, si returnea"a urmatorul
oras !are sa fie vi"itat pre!um si lungimea
drumului !atre a!esta& *)
void alege(int ultimul, int *min, int *3+min)
{
int 3;

)* /autam drumul minim de la ultimul
oras pana la orasele nepar!urse in!a& *)
*min = ,0*0,;
*3+min = 81;
for (3=0; 3<n; 3++)
if (9vi"itat#3$)
{
if (d#ultimul$#3$ < *min)
{
*min = d#ultimul$#3$;
*3+min = 3;

int main(void)
{
60:; *fin;
int i, 3;
int !ount, !ost, min, 3+min;

)* 2es!'idem fisierul pentru !itire in mod text& *)
fin = fopen(<!omis&in<, <rt<);
if (9fin)
{
printf(<;roare= nu pot des!'ide fisierul&>n<);
return 81;


)* /itim datele din fisier& *)
fs!anf(fin, <?d<, @n);
for (i=0; i<n; i++)
for (3=0; 3<n; 3++)
fs!anf(fin, <?d<, @(d#i$#3$));

)* Afisam pe e!ran datele preluate din fisier& *)
printf(<Avem ?d orase&>n<, n);
printf(<2istantele dintre orase sunt=>n<);
for (i=0; i<n; i++)
{
for (3=0; 3<n; 3++)
printf(<?d <, d#i$#3$);
printf(<>n<);

printf(<>n<);
)* 0nitial ni!i un oras nu este vi"itat& *)
for (i=0; i<n; i++)
vi"itat#i$ = 0;
)* 7rimul oras vi"itat este !el !u numarul <0<&
/ostul total este "ero deo!amdata& *)
drum#0$ = 0;
vi"itat#0$ = 1;
!ount = 1;
!ost = 0;

)* 7ar!urgem restul de n81 orase& *)
for (i=0; i<n81; i++)
{
)* Alegem urmatorul oras !are sa fie vi"itat& *)
alege(drum#!ount81$, @min, @3+min);

)* 7ar!urgem drumul minim gasit si vi"itam
un nou oras& *)
printf(<Am ales drumul (?d, ?d) de !ost ?d&>n<,
drum#!ount81$, 3+min, min);
drum#!ount$ = 3+min;
vi"itat#3+min$ = 1;
!ount++;
!ost += min;


)* 7ar!urgem drumul de la ultimul oras vi"itat
!atre primul oras si a!tuali"am !ostul
total& *)
!ost += d#drum#n81$$#0$;

)* Afisam drumul par!urs& *)
printf(<>n2rumul are !ostul ?d si este=>n<, !ost);
for (i=0; i<n; i++)
printf(<?d <, drum#i$);
printf(<0>n<);
return 0;

*i#ierul cu date de intrare pentru reeaua de ora#e din figura 2 este urmtorul,

A
0 A B C
A 0 B 1
B B 0 1
C 1 1 0
"mbun!t!iri Algoritmul greedy prezentat se poate mbunti pentru a furniza soluii mai aproape
de soluia optim. 1 variant de mbuntire este s nu se porneasc doar din primul ora# la
parcurgerea drumului. %e poate relua calculul avnd ca punct de pornire fiecare ora# pe rnd #i se
poate memora minimul global astfel obinut.
Probleme propuse
Conectarea ora#elor cu cost minim
Enun %e consider n ora#e. .entru diferite perec+i de ora#e (i, /), 6>i>n, 6>/>n se cunoa#te costul
conectrii lor directe c
i,/
. u toate perec+ile de ora#e pot fi conectate? pentru perec+ile care nu pot fi
conectate nu se precizeaz costul. %e cere s se construiasc o reea prin care oricare dou ora#e s
fie conectate ntre ele direct sau indirect #i costul total al conectrii s fie minim.
Reolvare %e poate arta c reeaua de conectare cerut este un arbore. .roblema mai este
cunoscut #i ca problema determinrii arborelui parial de cost minim ntr-un graf. .entru aceast
problem e!ist un algoritm greedy de rezolvare numit algoritmul lui !rim. n literatura de
specialitate e!ist argumentarea matematic a faptului c acest algoritm gse#te ntotdeauna soluia
optim de conectare a ora#elor.
%e construie#te arborele parial minim n manier greedy, adugnd cte un nod la fiecare
pas. -a nceput de tot arborele parial este vid, nu conine nici un nod. .rimul pas const n
adugarea unui nod arbitrar n arbore. .e urm, la fiecare pas se caut muc+ia de cost minim care
porne#te dintr-un nod de/a adugat la arbore #i a/unge ntr-un nod care nu este n arbore. %e adaug
n arbore nodul n care sfr#e#te muc+ia gsit.
% considerm spre e!emplu o reea de @ ora#e numerotate de la 6 la A. &osturile de
conectare a ora#elor sunt redate n figura 2.
*igura 2, &osturi de conectare a ora#elor pentru problema
conectrii ora#elor cu cost minim
Arborele minim este redat cu linii ngro#ate. El a fost construit pas cu pas, conform procedeului
descris mai sus. 'niial arborele a fost vid. -a primul pas s-a adugat un nod arbitrar, #i anume nodul
6.
.e urm s-a ales muc+ia de cost minim care pleac din nodul 6 ctre celelalte noduri.
=uc+ia de cost minim a fost (6,2) de cost 46. odul 2 a fost adugat n arbore.
-a urmtorul pas s-a ales muc+ia de cost minim care pleac din nodurile 6 sau 2 ctre
celelalte noduri. =uc+ia aleas a fost (2,4) de cost B. odul 4 a fost adugat n arbore.
-a urmtorul pas s-a ales muc+ia de cost minim care pleac din nodurile 6, 2 sau 4 ctre
nodurile nc neintroduse n arbore. =uc+ia aleas a fost (4,C) de cost 7. odul C a fost adugat n
arbore.
0rmtoarea muc+ie aleas a fost (C,5) de cost 2. odul 5 a fost adugat n arbore. Apoi a
fost aleas muc+ia (5,A) de cost 2 #i nodul A a fost adugat #i el n arbore.
.e urm a fost aleas muc+ia (4,7) de cost 5 #i nodul 7 a fost introdus n arbore. n acest
moment algoritmul s-a nc+eiat deoarece toate ora#ele au fost conectate la reea. &ostul total al
conectrii a fost 46 8 B 8 7 8 2 8 2 8 5 9 76.
Implementare =atricea costurilor, &, se reine ntr-un tablou bidimensional. .entru perec+ile de
ora#e ntre care nu se poate face legtur se va trece n matricea costurilor valoarea 6. n termeni
"reedy, mulimea noastr iniial de elemente A este muimea tuturor perec+ilor de ora#e ntre care
se poate stabili legtur direct. Adic A9;(i, /) D c
i,/
E6<. .entru graful din figura 4, mulimea A va
conine elementele ;(6,4), (6,2), (4,2), (4,7), (4,C), (2,7), (5,C), (5,A), (C,A)<.
%ubmulimea B pe care o cutm va conine o parte din perec+ile aflate n mulimea A. %e
poate demonstra c soluia optim B
*
conine n"1 perec+i atunci cnd numrul de ora#e este n
(presupunem c graful este cone!, adic se poate construi o reea care s conecteze toate ora#ele).
.entru construirea mulimii B, vom selecta ora#ele rnd pe rnd pentru a le aduga la reea.
Fom spune c un ora# este selectat atunci cnd el a fost conectat la reeaua de ora#e printr-o muc+ie
care face parte din mulimea B.
n implementare nu vom lucra cu mulimea A sub forma e!plicit de perec+i, ci vom folosi
matricea costurilor #. Fom etic+eta liniile #i coloanele matricei costurilor dup cum urmeaz.
Atunci cnd un ora# o
i
este selectat, linia i din matrice se marc$eaz, iar coloana i din matrice se
%terge.
.entru a alege urmtorul element din mulimea A care s fie prelucrat, cutm cel mai mic
cost din matricea costurilor din liniile marcate #i coloanele care nu sunt #terse. % zicem c cel mai
mic cost a fost gsit ca fiind elementul c
iGmin,/Gmin
. Atunci urmtorul element din mulimea A care va
fi prelucrat este perec+ea (iGmin,/Gmin).
Htergerea coloanelor din matricea costurilor nu va nsemna o #tergere fizic, ci doar una
logic. Fom folosi doi vectori prin care vom memora care linii sunt marcate #i care coloane sunt
#terse.
1 sc+ema de cod surs pentru rezolvarea acestei probleme arat astfel,
&&&
)* *umarul maxim de noduri din graf& *)
%define *+,A- .0
)* *umarul de orase& *)
int n;
)* ,atri!ea !osturilor de !one!tare a oraselor& *)
int !#*+,A-$#*+,A-$;
)* 4e!tor !are indi!a liniile mar!ate din matri!ea
!osturilor& mar!at#5$ va fi 1 pentru liniile
mar!ate si 0 pentru liniile nemar!ate& *)
int mar!at#*+,A-$;
)* 4e!tor !are indi!a !oloanele sterse din matri!ea
!osturilor& sters#5$ va fi 1 pentru !oloanele
sterse si 0 pentru !oloanele nesterse& *)
int sters#*+,A-$;
)* 6un!tie !are alege urmatorul element !are sa
fie prelu!rat din multimea A, adi!a o pere!'e
de orase intre !are sa se !onstruias!a drum&
De par!urg liniile mar!ate si !oloanele
nesterse din matri!ea !osturilor si se
alege !ostul minim&
De returnea"a !ostul minim gasit, si linia si
!oloana unde apare el& *)
void alege(int* min, int *i+min, int* 3+min)
{
&&&

int main(void)
{
&&&
)* Ai!i memoram mu!'iile alese pentru a fa!e parte din arbore&
E mu!'ie este memorata de pere!'ea (arbore#i$#0$, arbore#i$#1$)& *)
int arbore#*+,A-$#B$;
)* *umarul de mu!'ii introduse in arbore& *)
int !ount = 0;

&&&
)* /itim din fisier numarul de noduri din graf
si matri!ea !osturilor& *)
&&&

)* 0nitial ni!i un nod nu este ni!i mar!at ni!i
sters& 7entru asta initiali"am toate elementele
ve!torilor Fmar!atG si FstersG !u "ero& *)
&&&
)* 7ornim de la nodul <0<, motiv pentru !are
mar!am linia 0 si stergem !oloana 0& *)
mar!at#0$ = 1;
sters#0$ = 1;

&&&

)* /at timp mai avem noduri nepar!urse& *)
H'ile (9gata)
{
)* Alege urmatoarea pere!'e de noduri !are sa fie
prelu!rata& *odul Fi+minG va fi un nod de3a par!urs,
iar nodul F3+minG va fi un nod in!a nepar!urs& *)
alege(@min, @i+min, @3+min);
&&&
)* ,ar!am linia noului nod si stergem
!oloana lui& *)
mar!at#3+min$ = 1;
sters#3+min$ = 1;

)* Adaugam mu!'ia la arbore& *)
arbore#!ount$#0$ = i+min;
arbore#!ount$#1$ = 3+min;
!ount++;
&&&


)* Afisam arborele partial minim pe !are l8am gasit& *)
&&&
return 0;

*isierul cu date de intrare pentru graful din figura 2 este urmtorul,



C
0 B0 10 0 0 0 0
B0 0 I A 0 . 0
10 I 0 10 0 0 0
0 A 10 0 0 0 0
0 0 0 0 0 B B
0 . 0 0 B 0 .
0 0 0 0 B . 0

S-ar putea să vă placă și