Documente Academic
Documente Profesional
Documente Cultură
1 2 3 4 5
s=1 5 10 15 d=3 s=4 20 25 d=5
m=(1+3)/2=2 m=(4+5)/2=4
z123= z12+ z45= z4+ z5=20+0=20
z3=10+0=10
1 2 3 4 5
s=1 5 10 d=2 15 20 25
m=(1+2)/2=1 s=d=3 s=d=4 s=d=5
z12= z1+ z2=0+10=10 z3=0 z4=20 z5=0
1 2
s=d=1 5 10 s=d=2
z1=0 z2=10
Implementarea metodei divide et impera în acest exemplu se face astfel:
Subprogramul divizeaza()– Numărul de subprobleme în care se descompune problema
este 2 (k=2). Mulţimea datelor de intrare este divizată în două submulţimi disjuncte, prin
divizarea mulţimii indicilor în două submulţimi disjuncte de indici, adică mulţimea indicilor
[s,d] (unde s este primul indice, iar d ultimul indice) este divizată în două submulţimi disjunc-
te [s,m] şi [m+1,d], unde m este indicele din mijlocul intervalului: m=(s+d)/2. În subpro-
gram, procesul de divizare constă în determinarea mijlocului intervalului – m.
Subprogramul combina()– Combinarea soluţiei înseamnă adunarea celor două sume
obţinute prin rezolvarea celor două subprobleme. În subprogram sunt combinate cele
două valori obţinute din prelucrarea celor două intervale, adică se adună cele două
valori x şi y, obţinându-se soluţia z.
Subprogramul dei()– O subproblemă corespunde cazului de bază atunci când sub-
mulţimea conţine un singur element (se poate calcula suma, obţinându-se soluţia subpro-
blemei). Dacă s-a terminat procesul recursiv (prin procesul de divizare, cele două capete
ale intervalului au ajuns să fie identice), atunci se prelucrează cazul de bază (se calcu-
lează suma în variabila z, corespunzătoare soluţiei, astfel: dacă numărul v[s] este par,
atunci suma va fi chiar numărul; altfel, are valoarea 0); altfel, se apelează subproramul
pentru divizarea intervalului, se apelează subprogramul dei() pentru primul interval, se
apelează subprogramul dei() pentru al doilea interval şi se combină cele două rezultate.
#include<iostream.h>
int v[100],n;
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
void combina(int x,int y,int &z) {z=x+y;}
void dei(int s,int d,int &z)
{int m,x1,x2;
if (d==s)
if (v[s]%2==0) z=v[s]; else z=0;
else
{divizeaza(s,d,m); dei(s,m,x1); dei(m+1,d,x2); combina(x1,x2,z);}}
void main()
{int i,z; cout<<"n= ";cin>>n;
for(i=1;i<=n;i++) {cout<<"v["<<i<<"]="; cin>>v[i];}
dei(1,n,z); cout<<"suma= "<<z;}
Exemplul 2: Să se calculeze suma 12+23+ ... +n(n+1).
s=1 1 2 3 4 5 d=5
m=(1+5)/2=3
z=z12345= z123+ z45=20+50=70
s=1 1 2 d=2 3 4 5
m=(1+2)/2=1 s=d=3 s=d=4 s=d=5
z12= z1+ z2=2+6=8 z3=34=12 z4=45=20 z5=56=30
s=d=1 1 2 s=d=2
z1=12=2 z2=23=6
Implementarea metodei divide et impera în acest exemplu se face astfel:
Subprogramul divizeaza()– Numărul de subprobleme în care se descompune pro-
blema este 2 (k=2). Mulţimea datelor de intrare este divizată în două submulţimi disjunc-
te, prin divizarea mulţimii primelor n numere naturale în două submulţimi disjuncte, adi-
că mulţimea [s,d] (unde s este primul număr din mulţime, iar d ultimul număr din
mulţime) este divizată în două submulţimi disjuncte, [s,m] şi [m+1,d], unde m este nu-
mărul din mijlocul intervalului: m=(s+d)/2. În subprogram, procesul de divizare constă
în determinarea mijlocului intervalului, m.
Subprogramul combina()– Combinarea soluţiei înseamnă adunarea celor două sume
obţinute prin rezolvarea celor două subprobleme. În subprogram sunt combinate cele
două valori obţinute din cele două intervale (se adună cele două valori, x şi y) obţinân-
du-se soluţia z.
Subprogramul dei()– O subproblemă corespunde cazului de bază atunci când sub-
mulţimea conţine un singur element (se poate calcula termenul sumei – produsul celor
două numere consecutive – obţinându-se soluţia subproblemei). Dacă s-a terminat
procesul recursiv (prin procesul de divizare, cele două capete ale intervalului au ajuns
să fie identice), atunci se prelucrează cazul de bază (se calculează produsul în variabila
z, corespunzătoare soluţiei); altfel, se apelează subprogramul pentru divizarea inter-
valului, se apelează subprogramul dei() pentru primul interval, se apelează subpro-
gramul dei() pentru al doilea interval şi se combină cele două rezultate.
#include<iostream.h>
int n;
void divizeaza(int s,int d,int &m) {m=(s+d)/2;}
void combina(int x,int y,int &z) {z=x+y;}
void dei(int s,int d,int &z)
{int m,x1,x2;
if (d==s) z=s*(s+1);
else {divizeaza(s,d,m); dei(s,m,x1); dei(m+1,d,x2); combina(x1,x2,z);}}
void main()
{int z; cout<<"n= ";cin>>n; dei(1,n,z); cout<<"suma ="<<z; }
Complexitatea algoritmului divide et impera
Metoda divide et impera se bazează pe rezolvarea recursivă a subproblemelor în care
este divizată problema iniţială.
Atunci când un algoritm conţine un apel recursiv, timpul său de execuţie este dat de o formulă
recursivă care calculează timpul de execuţie al algoritmului pentru o dimensiune n a datelor
de intrare, cu ajutorul timpilor de execuţie pentru dimensiuni mai mici. Timpul de execuţie al
unui algoritm care foloseşte metoda divide et impera se bazează pe calculul timpilor de exe-
cuţie ai celor trei etape de rezolvare a problemei.
Metoda divide et impera se recomandă în următoarele cazuri:
algoritmul obţinut este mai eficient decât algoritmul clasic (iterativ) – de exemplu, algo-
ritmul de căutare într-un vector sortat şi algoritmii pentru sortarea unui vector;
rezolvarea problemei prin divizarea ei în subprobleme este mai simplă decât rezol-
varea clasică (iterativă) – de exemplu, problema turnurilor din Hanoi şi generarea unor
modele fractale.
1. 5. Metoda greedy
1.5.1. Descrierea metodei greedy
Metoda greedy se poate folosi pentru problemele în care, dându-se o mulţime finită A,
trebuie determinată o mulţime SA care să îndeplinească anumite condiţii. Metoda furni-
zează o singură soluţie, reprezentată prin elementele mulţimii S. Ca şi în cazul metodei
backtracking, soluţia problemei este dată de un vector S = {x1, x2, …, xn} ale cărui elemente
aparţin însă unei singure mulţimi A. Spre deosebire de metoda backtracking, metoda Greedy
nu găseşte decât o singură soluţie şi, în general, această soluţie este soluţia optimă.
Scop: identificarea problemelor în care soluţia optimă este o submulţime inclusă într-o
mulţime dată, care trebuie să îndeplinească anumite condiţii.
Enunţul problemei 1: Să se repartizeze optim o resursă (de exemplu, o sală de specta-
cole, o sală de conferinţe, o sală de sport) mai multor activităţi (spectacole, prezentări de
produse, respectiv meciuri) care concurează pentru a obţine resursa respectivă.