Sunteți pe pagina 1din 15

Voicu Ionut Radu ,cls a XII-a C

1
Voicu Ionut Radu ,cls a XII-a C

Consideratii teoretice

Explicarea numelui

In limba engleza cuvantul greedy inseamna lacom. Algoritmii de


tip greedy sut algoritmi lacomi. Ei vor sa construiasca intr-un
mod cat mai rapid solutia problemei fara a sta mult pe ganduri.
Algoritmii de tip greedy se caracterizeaza prin luarea
unor decizii rapide care duce la gasirea unei solutii a problemei.
Nu intotdeauna asemenea decizii rapide duc la o solutie optima,
dar vom vedea ca exista anumite tipuri de probleme unde se pot
obtine solutii optime sau foarte apropiate de optim.

Aplicabilitatea algoritmilor de tip Greedy

Algoritmii de tip Greedy se aplica la acele probleme unde datele


de intrare sun organizate sub forma unei multimi A ,si se cere
gasirea unei submultimi B A care sa indeplineasca anumite
conditii astfel incat sa fie acceptata ca solutie posibila.
In general pot sa existe mai multe submultimi BcA
care sa reprezinte soluti posibile ale problemei. Dintre toate
aceste submultimi B se pot selecta, conform unu anumit criteriu,
anumite submultimi B* care reprezinta solutii optime ale
problemei. Scopul este de a gasi, daca este posibil, una din
multimile B* . Daca acest lucru nu este posibil, atunci scopul

2
Voicu Ionut Radu ,cls a XII-a C

este gasirea unei multimi B care sa fie cat mai aproape de


multimile B* conform criteriului de optimalitate impus.

Modul de lucru al algoritmilor de tip Greedy

Construirea multimii B se face printr-un sir de decizii. Initial se


porneste cu mulimea vida (B = ). Fiecare decizie consta in
alegerea unui element din multimea A analiza lui si eventual
introducerea lui in multimea B. In functie de modul in care se iau
aceste decizii, multimea B se va apropia mai mult sau mai putin
de solutia optima B*. In cazul ideal vom avea B = B*.
Algoritmii de tip greedy nu urmaresc sa determine
toate solutiile posibile si sa aleaga dintre ele, conform criterlului
de optimalitate impus, solutiile optime. Dupa cum spune si
numele, algorltmil de tip greedy sunt caracterizati prin lacomie si
nu au rabdarea sa investigeze toate variantele posiblle de
alegere a solutiei. Ei incep construirea unei solutii pornind de la
multimea vida, apoi lucreaza in pasi, intr-un mod cat se poate de
hotarat: la fiecare pas se ia cate o decizie ,si se extinde solutia
cu cate un element.
La fiecare pas se analizeaza cate un element din
multimea A si se decide daca sa fie sau nu inclus in multimea B
care se construie,ste. Astfel se progreseaza de la cu un sir de

multimi intermediare ( , , , , ...), pana cand se obtine o

solutie finala B.

Implementare

Ca si schema generala de lucru, exista doua variante de


implementare a algoritmilor de tip Greedy.
Prima varianta foloseste doua functii carcteristice:alege si
posibil,alege este o functie care are rolul de a selecta urmatorul
3
Voicu Ionut Radu ,cls a XII-a C

element din multimea A care sa fie prelucrat. Functia posibil

verifica daca un element poate fi adaugat solutiei intermediare

astfel incat noua solutie care s-ar obtine sa fie o solutie

valida. Prezentam in continuare pseudocodul pentru aceasta


prima varianta greedy. Se considera ca numarul de elemente al
multimii A este n.

B = multimea vida
for (i=O; i<n; i++)

x = alege (A)
if (posibil ( B, x) )

* adauga elementul x la multimea B

Dificultatea la aceasta prima varianta consta in scrierea functiei


alege. Daca functia alege este bine conceputa, atunci putem fi
siguri ca solutia B gasita este o solutie optima. Daca functia
alege nu este foarte bine conceputa, atunci solutia B gasita va fi
doar o solutie posibila si nu va fi optima.Ea se poate apropia insa
mai mult sau mai putin de solutia optima B. In functie de criteriul
de selectie implementat.
A doua varianta de implementare difera de prima prin
faptul ca face o etapa initiala de prelucrare a multimii A. Practic
se face o sortare a elementelor multimii A, conform unui anumit
criteriu. Dupa sortare, elementele vor fi prelucrate direct in
ordirea rezultata. Prezentam in continuare pseudocodul pentru
aceasta a doua varianta greedy.

B = multimea vida prelucreaza(A)


for (i=0; i<n; i++)

x = A[i]
if (posibil(B,x)

4
Voicu Ionut Radu ,cls a XII-a C

* adauga elementul x la multimea B

La a doua varianta, dificultatea functiei alege nu a disparut, ci s-


a transferat functiei prelucreaza. Daca prelucrarea multimii A
este bine facuta, atunci se va ajunge in mod sigur la o solutie
optima. Altfel se va obtine doar o solutie posibila, mai mult sau
mai putin apropiata de optim.

Exemple

Problema comis-voiajorului

Enunt: Se condidera n orase. Se cunosc distantele dintre oricare


doua orase. Un comis-voiajor trebuie sa treaca prin toate cele n
orase. Se cere sa se determine un drum care porneste dintr-un
oras, trece exact o data prin fiecare din celelalte orase si apoi
revine la primul oras, astfel incat lungimea drumului sa fie
minima.

Rezolvare: Pentru gasirea unei solutii optime la aceasta problema


este nevoie de algoritmi cu timp de rulare foarte mare (de ordin

exponential 0( )). In situatiile practice aemenea algoritmi cu

timp foarte mare de rulare nu sunt acceptabili. Ca urmare se


face un compromis si se accepta algoritmi care nu gasesc
solutia optima ci doar o solutie aproape de optim, dar au in
schimb un timp de rulare mic. Propunem in continuare o solutie
greedy la aceasta problema. Ideea este urmatoarea. Se porneste
dintr-un oras oarecare. Se cauta drumul cel mai scurt care
pleaca din orasul respectiv catre orase nevizitate inca. Se
pareurge acel drum si se ajunge intr-un alt oras. Aici din nou se
cauta cel mai scurt drum catre orasele nevizitate inca. Se
pareurge si acest drum, ajungandu-se intr-un nou oras. Repetand

5
Voicu Ionut Radu ,cls a XII-a C

acesti pasi se pareurg toate orasele. La final se pareurge drumul


care duce inapoi spre primul oras.

Sa consideram exemplul din figura 1. Avem 4 orase cu distantele


reprezentat in figura.

Figura 1: Retea de orase pentru problema comis-voiajorului

Pornim vizitarea oraselor din orasul 0. De aiei alegem drumul cel


mai scurt catre orasele nevizitate ,si anume (0,2) de lungime 2.
Ajunsi in orasul 2, alegem din nou drumul eel mai scurt spre
orasele nevizitate, si anume (2,3) de lungime 1. Din orasul 3 mai
avem doar un singur oras nevizitat, 1, asa ca alegem drumul spre
el (3,1) de lungime 1. In acest moment am parcurs toate orasele
si ne reintoarcem in orasul 0 pe drumul (1,0) de lungime 4.
Drumul rezultat este 0, 2, 3, 1, 0, iar distanta totala de parcurs
este 2 + 1 + 1 + 4 = 8.

Implementare: Distantele intre orase le memoram intr-un tablou


bidimensional D.

Distanta intre orasele (i,j) va fi memorata in elementul (i,j) al


matricii. In termeni Greedy, multimea initiala A este multimea
tuturor perechilor de orase. Pentru reteaua de orase din figura 2
multimea A contine elementele {(0,1), (0,2), (0,3), (1,2), (1,3),
(2,3)}. Multimea B care trebuie gasita va contine o parte din

6
Voicu Ionut Radu ,cls a XII-a C

aceste perechi de orase, si anume acele perechi care inlantuite


sa formeze un drum ce trece prin toate orasele. Daca avem un
numar de n orase, atunci multimea B va contine n perechi de
orase.
In implementare nu vom lucra cu multimea A sub aceasta
forma explicita de perechi de orase, ci vom folosi matricea
distantelor D. De asemenea drumul comisvoiajorului nu il vom
pastra sub forma de perechi de orase, ci sub forma unui sir al
oraselor.
Pentru a memora drumul parcurs de comis-voiajor, folosim un
tablou unidimensional drum. In acest tablou vom memora indicii
oraselor parcuse, in ordinea parcurgerii.
Pentru a sti care orase au fost parcurse, facem o marcare
logica a oraselor folosind un tablou unidimensional vizitat.
Elementele din acest tablou care au valoarea 1 reprezinta orase
vizltate.
Imbunatatiri: Algoritmul greedy prezentat se poate
imbunatati pentru a furniza solutii mai aproape de solutia optima.
O varianta de imbunatatire este sa nu se porneasca doar din
primul oras la parcurgerea drumului. Se poate relua calculul
avand ca punct de pornire oricare oras pe rand si se poate
memora minimul global astfel obtinut.

Problema rezolvata in Pascal:

program comis-voiajor;
var s:array[1..90 of integer;
a:array[1..9,1..9] of integer;
n,i,j,v,vs,vs1,min,cost:integer;
begin
write('numar noduri=');
readln(n);
{citesc matrice}
for i:=1 to n do
for j:=i+1 to do

7
Voicu Ionut Radu ,cls a XII-a C

begin
write('a[',i,',',j,']=');
readln(a[i,j]);
a[j,i]:=a[i,j];
end;
{Pentru fiecare nod}
write('nod de pornire ');
readln(v);s[v]:=1;
vs1:=v
write('drumul ce trece prin ');
for i:=1 to n-1 do
begin
min:=30000;
for j:=1 to n do
if (a[v,j]<>0 and(s[j]=0) and (min>a[v,j])
then
begin
min:=a[v,k];
vs:=j
end;
cost:=cost+a[v,vs];
write(vs,' ');
s[vs]:=1;
v:=vs;
end;
cost:=cost+a[vs1,v];
writeln('cost=' ,cost);
end.

Problema rucsacului

Se da un rucsac de volum V si mai multe obiecte de greutati


G1,G2,...Gn ce au volumele V1, V2,..., Vn. Se cere sa se incarce
rucsacul la greutatea maxima utilizand cate un obiect din fiecare
tip.

Se observa ca cea mai buna metoda de incarcare a rucsacului ar


fi sa introducem obiectele in ordine descrescatoare a densitatii
acestora. Deci vom calcula densitatile obiectelor p1=G1/V1,
p2=G2/V2,. ..pn=Gn/Vn ,si vom sorta obiectele in ordine

8
Voicu Ionut Radu ,cls a XII-a C

descrescatoare a densitatii. Acestea fiind realizate aplicam


metoda Greedy:

1. La inceput volumul obiectelor adaugate V0=0


2. Se alege un obiect (in ordine descrescatoare a densitatii)
3. Verificam daca putem adauga obiectul (daca prin
adaugare nu se depaseste
volumul admis
4. Repetam pana caand s-au terminat obiectele sau s-a atins
volumul dorit

Problema rezolvata in Pascal:


program rucsac;
type tablou=array [1..4] of real;
matrice=array [1..10] of tablou;
{In prima coloana se inscrie costul,
In a II - greutatea, in a III - eficienta,
si in a IV - a cata parte se ia
tabloul c il folosim la sortare, "al treilea pahar"}
var a:matrice; c:tablou; f:text;
loc,n,g,i,j:integer; max,castig,dg:real;
begin
assign (f,'rucsac.txt'); reset (f);
readln(f,n,g);
for i:=1 to n do
begin readln(f,a[i,1],a[i,2]);
a[i,3]:=a[i,1]/a[i,2]; a[i,4]:=0;
end;
{sortam tabloul dupa eficienta}
for i:=1 to n-1 do
begin max:=a[i,3];loc:=i;
for j:=i+1 to n do
if a[j,3]>max then begin max:=a[j,3]; loc:=j; end;
c:=a[i]; a[i]:=a[loc]; a[loc]:=c;
end;
{Aflam cat din fiecare obiect se pune in rucsac si calculam castigul}
castig:=0;
i:=1; dg:=g;
writeln ('greutatea ','costul ','eficienta ','rucsac');
while (i<=n) and (dg>0) do
begin;
if dg>=a[i,2]
then begin castig:=castig+a[i,1];
dg:=dg-a[i,2]; a[i,4]:=1;
end
else begin castig:=castig+dg*a[i,3];
a[i,4]:=dg/a[i,2];dg:=0;
end;
writeln (a[i,1]:6:2,a[i,2]:8:2,a[i,3]:12:2,a[i,4]:10:2);
9
Voicu Ionut Radu ,cls a XII-a C

i:=i+1;
end;
writeln ('greutatea rucsacului este ',g-dg:0:2);
writeln ('costul este ',castig:0:2);
end.

3. Probleme pentru care metoda Greedy nu determina solutia


optima

Problema determinarii drumului minim

Se da un graf G si se cere sa se determine drumul minim intre


doua noduri ale sale.

Metoda Greedy se poate aplica astfel:


1. Pornim din nodul de start x.
2.Alegem cel mai scurt drum spre nodul urmator.
3.Repetam pana cand se ajunge la nodul destinatie

Alegem ccl mai scurt drum spre nodul urmator. Repetam pana
cand se ajunge in nodul destinatie
Pentru exemplele urmatoare metoda gaseste drumul optim intre
1 si 4 ca fiind →1→2→3 → 4
In in imaginea din stanga solutia este corecta.
Dar in cazul celei din dreapta metoda da gres

Problema platii unei sume cu bacnote(moenzi) de valoare data

10
Voicu Ionut Radu ,cls a XII-a C

Sa se efectueze plata uinei sume S utilizand un numar minim de


monezi.Valorile monezilor se cunosc.

Metoda Greedy se poate aplica astfel:


1.Fie suma care a mai ramas de platit X=S
2.Sa alege moneda de valoare maxima Mi(astefel incat Mi
<=X)
3.Se calculeaza nr.maxim de monezi Mi ce pot fi date (n=X
div Mi )
4.Repetam pana cand restul sumei de platit este zero

Presupunem ca avem 5 monezi de valori:100,50,20,3.


Daca suma care trebuie platita Daca suma care trebuie
este 370 atunci avem evolutia: platita este 365 atunci avem
evolutia:

Suma Monede Suma Monede selectate


curenta selectate curent
de plata a Valoare Numar
Valoare Numar deplata

370 100 3 365 100 3

70 50 1 65 50 1

20 10 2 15 10 1

5 3 1
11
2 ... ...
Voicu Ionut Radu ,cls a XII-a C

Problema rezolvata in Pascal:

Program plata;
type tablou=array[1..3,1..7] of integer;
var s,ss,i : integer; a:tablou; f:text;
{In primul rind al tabelului vom pastra nominalul bancnotelor}
{In al doilea rind - numarul bancnotelor citite din fisier}
{In al treilea rind - numarul bancnotelor obtinute la schimb}
Procedure Afisare(sa:integer);
begin writeln('suma ',s);
if sa<>0
then writeln('nu poate fi transformata cu bancnotele date ')
else
begin writeln('se plateste cu urmatoarele bancnote');
for i:=1 to 7 do
if a[3,i]<>0
then writeln('bancnote de ',a[1,i]:6,' sau folosit ',a[3,i]);
end
end; { Afisare }
Procedure calcul(var sa:integer);
var nb:integer;
begin
i:=7;
while (i>=1) and (sa>0) do
begin nb:=sa div a[1,i];
if nb<>0 then if nb>= a[2,i]
then a[3,i]:=a[2,i]
else a[3,i]:=nb;
sa:=sa-a[3,i]*a[1,i];
i:=i-1;
end;
end; { calcul }
begin
a[1,1]:=1;
a[1,2]:=5;
a[1,3]:=10;
a[1,4]:=50;
a[1,5]:=100;
a[1,6]:=200;
a[1,7]:=500;
assign (f,'bani.in'); reset(f);
for i:=1 to 7 do readln(f,a[2,i]);
write ('introduceti suma de lei S ')
;readln(s);
ss:=s;
calcul(ss);
Afisare(ss);
end.

Probleme propuse

12
Voicu Ionut Radu ,cls a XII-a C

Conectarea oraselor cu cost minim

Enunt: Se considera n orase. Pentru diferite perechi de orase (i,


j), 0<i<n, 0<j<n se cunoaste costul conectarii lor directe c.i,j Nu
toate perechile de orase pot fi conectate, pentru perechile care
nu pot fi conectate nu se precizeaza costul. Se cere sa se
construiasca o retea prin care oricare doua orase sa fie
conectate intre ele direct sau indirect si costul total al conectarii
sa fie minim.

Rezolvare: Se poate arata ca reteaua de conectare ceruta este


un arbore. Problema mai este cunoscuta si ca problema
determinarii arborelui partial de cost minim intr-un graf. Pentru
aceasta problema exista un algoritm greedy de rezolvare numit
algoritmul lui Prim. In literatura de specialitate exista
argumentarea matematica a faptului ca acest algoritm gasestes
intotdeauna solutia optima de conectare a oraselor.
Se construieste arborele partial minim in maniera greedy,
adaugand cate un nod la fiecare pas. La mceput de tot arborele
partial este vid, nu contine nici un nod. Primul pas consta in
adaugarea unui nod arbitrar in arbore. Pe urma la fiecare pas se
cauta muchia de cost minim care porneste dintr-un nod deja
adaugat la arbore si ajunge intr-un nod care nu este in arbore. Se
adauga in arbore nodul in care sfarseste muchia gasita.
Sa consideram spre exemplu o retea de 7 orase numerotate de la
0 la 6. Costurile de conectare a oraselor sunt redate in figura 2.

13
Voicu Ionut Radu ,cls a XII-a C

Figura 2: Costuri de conectare a oraselor pentru problema conectarii oraselor cu cost minim

Arborele minim este redat cu linii ingrosate. El a fost construit


pas cu pas, conform procedeului descris mai sus. Initial arborele
a fost vid. La primul pas s-a adaugat un nod arbitrar si anume
nodul 0.
Pe urma s-a ales muchia de cost minim care pleaca din
nodul 0 catre celelalte noduri. Muchia de cost minim a fost (0,2)
de cost 10. Nodul 2 a fost adaugat in arbore.
La urmatorul pas s-a ales muchia de cost minim care
pleaca din nodunle 0 sau 2 catre celelalte noduri. Muchia aleasa
a fost (2,1) de cost 9. Nodul 1 a fost adaugat in arbore.
La urmatorul pas s-a ales muchia de cost minim care
pleaca din nodurile 0,2 sau 1 catre nodurile inca neintroduse in
arbore. Muchia aleasa a fost (1,5) de cost 3. Nodul 5 a fost
adaugat in arbore.
Urmatoarea muchie aleasa a fost (5,4) de cost 2. Nodul 4
a fost adaugat in arbore. Apoi a fost aleasa muchia (4,6) de cost
2 ,si nodul 6 a fost adaugat si el in arbore.
Pe urma a fost aleasa muchia (1,3) de cost 4 si nodul 3 a
fost introdus in arbore. In acest moment algoritmul s-a incheiat
deoarece toate orasele au fost conectate la retea. Costul total al
conectarii a fost 10 + 9 + 3 + 2 + 2 + 4 = 30.

Implementare: Matricea costurilor, C, se retine intr-un tablou


bidimensional. Pentru perechile de orase intre care nu se poate

14
Voicu Ionut Radu ,cls a XII-a C

face legatura se va trece in matricea costurilor valoarea 0. In


termeni Greedy, multimea noastra initiala de elemente A este
multimea tuturor perechilor de orase intre care se poate stabili
legatura directa. Adica A={(i, j) |I ci,j>O}. Pentru graful din figura 1,
multimea A va contine elementele {(0,1), (0,2), (1,2), (1,3), (1,5),
(2,3), (4,5), (4,6), (5,6)}
Submultimea B pe care o cautam va contine o parte din perechile
aflate in multimea A. Se poate demonstra ca solutia optima B
contine n-l perechi atunci cand numarul de orase este n
(presupunem ca graful este conex, adica se poate construi o
retea care sa conecteze toate orasele).
Pentru construirea multimii B. vom selecta orasele rand
pe rand pentru a le adauga la retea. Vom spune ca un oras este
selectat atunci cand el a fost conectat la reteaua de orase printr-
o muchie care face parte din multimea B.
In implementare nu vom lucra cu multimea A sub forma
explicita de perechi, ci vom folosi matricea costurilor C. Vom
eticheta liniile si coloancle matrici costurilor dupa cum urmeaza.
Atunci cand un oras oi este selectat, linia i din matrice se
marcheaza, iar coloana i din matrice se sterge.
Pentru a alege urmatorul element din multimea A care sa
fie prelucrat, cautam cel mai mic cost din matricea costurilor din
liniile marcate si coloanele care nu sunt sterse. Sa zicem ca cel
mai mic cost a fost gasit ca fiind elementul Ci_min_j_min. Atunci
urmatorul element din multimea A care va fi prelucrat este
perechea (i_min,j_min).
Stergerea coloanelor din matricea costurilor nu va
insemna o ,stergere fizica, ci doar una logica. Vom folosi doi
vectori prin care vom memora care linii sunt marcate si care
coloane sunt sterse.

15

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