Sunteți pe pagina 1din 7

Note de laborator Specializare

Algoritmi si structuri de date 2 Info 1

Laborator 3
Descriere: Metoda optimului local – Greedy

1. Introducere

Metoda Greedy are ın vedere rezolvarea unor probleme de optim ın care optimul global se
determina din estimari succesive ale optimului local. Metoda Greedy se aplica urmatorului tip de
problema: dintr-o multime de elemente A, se cere sa se determine o submultime B, care
ındeplineste anumite conditii. De exemplu, alegerea ordinii optime de efectuare a unor lucrari,
alegerea traseului optim pentru vizitarea unor obiective turistice, etc. Deoarece este posibil sa existe
mai multe solutii se va alege solutia care maximizeaza sau minimizeaza o anumita functie obiectiv.

O problem a poate fi rezolvata prin tehnica (metoda) Greedy daca ındeplineste proprietatea: daca B
este o solutie, iar C este inclusa ın B, atunci si C este o solutie. Pornind de la aceasta conditie, initial
se presupune ca B este multimea vida si se adauga succesiv elemente din A ın B, ajungand la un
optim local. Dar, succesiunea de optimuri locale nu asigura, ın general, optimul global. Daca se
demonstreaza ca succesiunea de optimuri locale conduce la optimul global, atunci metoda Greedy
este aplicabila.

Exista urmatoarele variante ale metodei Greedy:


ƒ Se pleaca de la solutia vida pentru multimea B si se ia pe rand cate un element din multimea
A. Daca elementul ales ındeplineste conditia de optim local, el este introdus ın multimea B.
ƒ Se ordoneaza elementele multimii A si se verifica daca un element ındeplineste conditia de
apartenenta la multimea B.

2. Algoritmi Greedy

Algoritmii greedy sunt ın general simpli si sunt folositi la rezolvarea unor probleme de optimizare.
In cele mai multe situatii de acest fel avem:

ƒ o multime de candidati (lucrari de executat, varfuri ale grafului, etc.)


ƒ o functie care verifica daca o anumita multime de candidati constituie o solutie posibila, nu
neaparat optima, a problemei
ƒ o functie care verifica daca o multime de candidati este fezabila, adica daca este posibil sa
completam aceasta multime astfel ıncat sa obtinem o solutie posibila, nu neaparat optima, a
problemei
ƒ o functie de selectie care indica la orice moment care este cel mai promitator dintre
candidatii ınca nefolositi
ƒ o functie obiectiv care da valoarea unei solutii (timpul necesar executarii tuturor lucrarilor
ıntr-o anumita ordine, lungimea drumului pe care l-am gasit, etc) si pe care urmarim sa o
optimizam (minimizam/maximizam)

Pentru a rezolva problema de optimizare, cautam o solutie posibila care sa optimizeze valoarea
functiei obiectiv.

Un algoritm greedy construieste solutia pas cu pas. Initial, multimea candidatilor selectati este vida.
La fiecare pas, ıncercam sa adaugam la aceasta multime pe cel mai promitator candidat, conform
functiei de selectie. Daca, dupa o astfel de adaugare, multimea de candidati selectati nu mai este
ASD

fezabila, eliminam ultimul candidat adaugat;acesta nu va mai fi niciodata considerat. Daca, dupa
adaugare, multimea de candidati selectati este fezabila, ultimul candidat adaugat va ramane de
acum incolo ın ea. De fiecare data cand largim multimea candidatilor selectati, verificam daca
aceasta multime nu constituie o solutie posibila a problemei. Daca algoritmul greedy functioneaza
corect, prima solutie gasita va fi totodata o solutie optima a problemei.

Solutia optima nu este ın mod necesar unica: se poate ca functia obiectiv sa aiba aceeasi valoare
optima pentru mai multe solutii posibile.

Descrierea formala a unui algoritm greedy general este:

function greedy(C) // C este multimea candidatilor


S←∅ // S este multimea ın care construim solutia
while not solutie(S) and C ≠ ∅ do
x ← un element din C care maximizeaza/minimizeaza select(x)
C ← C − {x}
if fezabil(S ∪ {x}) then S ← S ∪ {x}

if solutie(S) then return S


else return ”nu exista solutie”

3. Plata restului

Un exemplu simplu de algoritm greedy este cel folosit pentru rezolvarea urmatoarei probleme:
trebuie sa dam restul unui client, folosind un numar cat mai mic de monezi. In acest caz, elementele
problemei sunt:
ƒ candidatii: multimea initiala de monezi, pentru care presupunem ca avem un numar
nelimitat din fiecare tip de moneda
ƒ o solutie posibila: valoarea totala a unei astfel de multimi de monezi selectate
trebuie sa fie exact valoarea pe care trebuie sa o dam ca rest
ƒ o multime fezabila: valoarea totala a monezilor selectate ın aceasta multime nu este mai
mare decat valoarea pe care trebuie sa o dam ca rest
ƒ functia de selectie: se alege cea mai mare moneda din multimea de candidate ramasa
ƒ functia obiectiv: numarul de monezi folosite ın solutie; se doreste minimizarea acestui
numar

import java.io.*;

public class Rest{

static int [] a,x,xopt;


static int n,val,rest,min;

public void include (int k){


rest-=a[k]*x[k];
}

public void exclude(int k){


rest+=a[k]*x[k];
}

public boolean posibil(int k){


if(k<n)
return a[k]*x[k]<=rest;
ASD

else
return a[k]*x[k]==rest;
}

public void scrieSol(){


for (int i=0;i<n;i++)
System.out.print(x[i]+"*"+a[i]+" ");
System.out.print("Monede"+"\n");
}

public boolean solutie(){


int suma=0;
for (int i=0;i<n;i++)
suma+=x[i]*a[i];

if (suma==val) {
int nrMonede=0;
for (int i=0;i<n;i++) //nr total de monede necare
nrMonede+=x[i];

if(nrMonede<min){
min=nrMonede;
for (int i=0;i<n;i++)
xopt[i]=x[i]; //solutia optima
}

return true;
}
else return false;
}

public void cautaSol(int k){


if (solutie()) scrieSol();

else if (k<n){
for(int i=0;i<val;i++){
x[k]=i;

if (posibil(k)){
include(k);
cautaSol(k+1);
exclude(k);
}
}
}
}

public static void main(String []args) throws Exception{

BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));

System.out.println("Nr. monede diferite:");


n=Integer.parseInt(stdin.readLine());

a=new int[n];
x=new int[n];
xopt=new int[n];

System.out.println("valoarea fiecarei monede :");

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


System.out.print("a["+i+"]=");
a[i]=Integer.parseInt(stdin.readLine());
}
ASD

System.out.println("Suma de plata:");
rest=Integer.parseInt(stdin.readLine());

val=rest;
min=10000;

Rest r=new Rest();


r.cautaSol(0);

System.out.println("******************");
System.out.println("Nr minim de monede:");

for(int i=0;i<n;i++){
if(xopt[i]!=0){
System.out.print(xopt[i]+"*"+a[i]+" ");
System.out.print("Monede"+"\n");
}
}
} //end main
}

4. Problema continua a rucsacului

Realizati un program care rezolva problema rucsacului, sau problema selectiei optime. Fiind date n
obiecte, fiecare cu greutatea g[i] si valoarea v[i] si un rucsac cu capacitatea totala gt, sa se
determine ce obiecte trebuie selectate pentru a fi luate in rucsac astfel incat greutatea lor totala sa
nu depaseasca gt si valoarea lor sa fie maxima. Datele de intrare vor fi preluate dintr-un fisier
rucsac.in

Notam cu xi ∈ [0, 1] partea din obiectul i care a fost pusa ın rucsac. Practic, trebuie sa maximizam
functia

Pentru rezolvare vom folosi metoda greedy. O modalitate de a ajunge la solutia optima este de a
considera obiectele ın ordinea descrescatoare a valorilor utilitatilor lor date de raportul

si de a le ıncarca ıntregi ın rucsac pana cand acesta se umple. Din aceasta cauza presupunem ın
continuare ca

Vectorul x = (x1, x2, ..., xn) se numeste solutie posibila daca

iar o solutie posibila este solutie optima daca maximizeaza functia f. Vom nota Gp greutatea
permisa de a se ıncarca ın rucsac la un moment dat. Conform strategiei greedy, procedura de
rezolvare a problemei este urmatoarea:
ASD

Vectorul x are forma x = (1, ..., 1, xi, 0, ..., 0) cu xi ∈ (0, 1] ¸si 1 ≤ i ≤ n.

import java.io.*;

public class Rucsac{

static int x[], xopt[]; // vectori solutie : obiecte selectate


static int g[], v[]; // greutati si valori obiecte
static int sac[]; // continut rucsac
static int n,gt,nopt,gp,vp,vmax,val ;

boolean posibil (int k) {


int ob=x[k]; // nr.obiect ales in pasul k
if (sac[ob] == 1 || (g[ob]+gp > gt) )
return false;
return true;
}

void scrieSol(int k) {
int i;
if (vmax < vp) {
vmax=vp; nopt=k-1;
for (i=0;i<k;i++)
xopt[i]=x[i];
}
}

boolean solutie(int k) {
int i; // numar obiect
for (i=0;i<n;i++)
if ( sac[i] ==0 && g[i] <= gt-gp)
return false; // un obiect ob incape in sac
return true;
}

void include (int k) {


int ob=x[k]; // numar obiect
sac[ob]=1;
gp=gp+g[ob]; vp=vp+v[ob];
}

void exclude (int k) {


int ob=x[k]; // numar obiect
sac[ob]=0;
gp=gp-g[ob]; vp=vp-v[ob];
}

void cautSol (int k) {


int i;
if ( solutie(k))
scrieSol(k);
ASD

else
for (i=0;i<n;i++) {
x[k]=i;
if (posibil(k)) {
include(k);
cautSol (k+1);
exclude(k);
}
}
}

public static void main (String [] args) throws Exception{

BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));

System.out.println("Greutatea totala a rucsacului este :");

gt=Integer.parseInt(stdin.readLine());

System.out.println("Numarul de obiecte aflate la dispozitie :");

n=Integer.parseInt(stdin.readLine());

g=new int[n];
v=new int[n];

xopt=new int[n];
x=new int[n];

sac=new int[n];

System.out.println("Valoarea si greutatea fiecarui obiect:");

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


System.out.print("g["+i+"]=");
g[i]=Integer.parseInt(stdin.readLine());
System.out.print("v["+i+"]=");
v[i]=Integer.parseInt(stdin.readLine());
System.out.println("***********");
}

Rucsac r=new Rucsac();

vmax=0; val= 0;
gp=0; vp=0;

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


sac[i]=0;

r.cautSol (0);

System.out.println("Solutia optima este"+ vmax);

System.out.println("Obiectele ");
for (int i=0;i<=nopt;i++)

System.out.print((xopt[i]+1) +" ");


}
}

5. Exercitii

5.1 Intre insulele unui arhipelag exista n poduri .Un turist isi propune sa viziteze aceste poduri , o
singura data , pornind de la o anumita insula . Pozitia podurilor este data sub forma unei matrici.
ASD

Elementele matricei vor fi preluate dintr-un fisier aflat pe disc. Sa se afiseze toate posibilitatile de
parcurgere a celor n poduri.

5.2 Un comis voiajor trebuie sa viziteze un numar de n orase. Initial el se va afla in orasul notat cu
1. El nu doreste sa treaca de doua ori prin acelasi oras, iar la intoarcere sa revina in orasul 1.
Cunoscand legaturile existente intre orase, sa se gaseasca toate drumurile posibile pe care le poate
efectua comis-voiajorul.

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