Sunteți pe pagina 1din 5

Metoda Divide et impera

Metoda Divide et Impera (Imparte si Stapaneste) este o metoda de programare care se


aplica problemelor care pot fi descompuse in subprobleme independente, similare problemei
initiale, de dimensiuni mai mici si care pot fi rezolvate foarte usor.  
Procesul se reia pana cand (in urma descompunerilor repetate) se ajunge la probleme care
admit rezolvare imediata.
  Metoda presupune:
Descompunerea problemei Pb curente in subprobleme independente SubPbi.
In cazul in care subproblemele SubPbi. admit o rezolvare imediata se compun solutiile si se rezolva
problema Pb.
Altfel se descompun in mod similar si subproblemele SubPbi.
Evident, nu toate problemele pot fi rezolvate prin utilizarea acestei tehnici.
Majoritatea algoritmilor de Divide et Impera presupun prelucrari pe tablouri (dar nu obligatoriu).
Aceasta metoda (tehnica) se poate implementa atat iterativ dar si recursiv. Dat fiind ca problemele
se impart impart in subprobleme in mod recursiv, de obicei impartirea  se realizeaza pana cand sirul
obtinut este de lungime 1, caz in care rezolvarea subproblemei este foarte usoara, chiar banala.
Spre exemplu fie un vector X=[x1, x2, x3, …xi … xmij… xj, …xn] asupra caruia se aplica o prelucrare.
Pentru orice secventa din vector delimitata de indecsii  st si dr, st<dr  exista o valoare p astfel incat
prin prelucrarea secventelor :
                        xst, xst+1, xst+2, xst+3, …xmij  si xmij+1, xmij+2, xpmij3, …xdr
 se obtin solutiile corespunzatoare celor doua subsiruri care prin compunere conduc la obtinerea
solutiei prelucrarii secventei:
                                    xst, xst+1, xst+2, xst+3, …xdr 

Maximul dintr-un vector

Se citește un vector cu n componente, numere naturale. Se cere să se tipărească valoarea


maximă.
Funcția căutată va genera valoarea maximă dintre numerele reținute în vector pe o poziție dintre st
și dr (inițial, st=1, dr=n). Pentru aceasta, se procedează astfel: dacă st=dr, valoarea maxima va fi v[st];

în caz contrar, se imparte vectorul în doi subvectori - presupunem varianta pentru paralelizare pe 2
procesoare. Se calculează mijlocul m al intervalului [st, dr]: m = (st+dr) div 2. Primul subvector va
conține componentele de la st la m, al doilea va conține componentele de la (m+1) la dr; se rezolvă
subproblemele (aflându-se astfel maximul pentru fiecare din subvectori), iar soluția curentă va fi
dată de valoarea maximă dintre rezultatele celor două subprobleme.

#include <iostream>
using namespace std;

int v[10],n;
int max(int st, int dr)
{ int a, b, mij;
if (st==dr)
return v[st];
else
{ mij = (st+dr)/2;
a = max(st, mij);
b = max(mij+1, dr);
if (a>b)
return a;
else
return b;
}
}
int main( )
{ int i;
cout<<"n=";cin>>n;
for(i=1; i<=n; i++)
{ cout<<"v["<<i<<"]=";
cin>>v[i];
}
cout<<"max="<<max(1,n);

return 0;
}

Cmmdc inntr-un vector

using namespace std;


int v[10],n;

int cmmdc(int st, int dr)


{ int a, b, mij;
if (st<dr)
{ mij = (st+dr)/2;
a = cmmdc(st, mij);
b = cmmdc(mij+1, dr);
while(a>b)
if(a>b)
a=a-b;
else
b=b-a;
return a;
}
else return v[st];
}
int main( )
{ int i;
cout<<"n=";cin>>n;
for(i=1; i<=n; i++)
{ cout<<"v["<<i<<"]=";
cin>>v[i];}
cout<<cmmdc(1,n);
return 0;
}
Produsul intr-un vector

Să se calculeze produsul a n numere intregi.


Schema problemei:  generalizare:
Soluţie:  divide-et-impera
divide: mij = [(st + dr)/2]
subprobleme: produs(v[st..mij]), produs(v[mij+1..dr])
asamblare: înmulţeşte rezultatele subsecvenţelor produs(v[st..mij]) şi produs(v[mij+1..dr])

#include <iostream>
using namespace std;

int v[10],n;
int produs(int st, int dr)
{ int p1, p2, mij;
if (st==dr)
return v[st];
else
{ mij =(st+dr)/2;
p1 = produs(st, mij);
p2 = produs(mij+1, dr);
return p1*p2;}
}
int main( )
{ int i;
cout<<"n=";cin>>n;
for(i=1; i<=n; i++)
{ cout<<"v["<<i<<"]=";
cin>>v[i];
}
cout<<"produs="<<produs(1,n);

return 0;
}
Cautarea binara

Se citește un vector cu n componente numere întregi (numerele se presupun ordonate


crescător) și o valoare întreagă ("x"). Să se decidă dacă x se găsește sau nu printre numerele citite,
iar în caz afirmativ să se tipărească 1 altfel -1.

O rezolvare în care x se compară pe rând cu toate cele n componente reprezintă o pierdere de


performanță (nu exploatează faptul că cele n valori sunt în secvență crescătoare). Algoritmul care va
fi propus este optim și se poate spune că face parte dintre algoritmii "clasici".

Funcția care va fi implementată va decide dacă valoarea căutată se găsește printre numerele aflate
pe poziții de indice cuprins între st și dr (inițial, st=1, dr=n). Pentru aceasta, se va proceda astfel:

Dacă st<dr problema se descompune astfel:

• dacă x coincide cu valoarea de la mijloc, aflată pe poziția de indice (st+dr)/2, se returneaza 1 și se


revine din apel (problema a fost rezolvată).

 dacă x este mai mic decât valoarea testată (din mijloc), înseamnă că nu se poate afla pe pozițiile
din partea dreaptă, întrucât acestea sunt cel puțin mai mari decât valoarea testata
x se poate găsi doar printre componentele cu indice între st și mij-1, caz în care se
reapelează funcția cu acești parametri;

• dacă x este mai mare decât valoarea testată (din mijloc), înseamnă că nu se poate afla în stânga; se
poate găsi doar printre componentele cu indicele între mij+1 și st, caz în care se reapelează funcția
cu acești parametri.

• dacă nu mai sunt alte elemente de analizat (pentru că st=dr și valoarea din mijloc, v[mij], nu
coincide cu x), se concluzionează că x nu apare în cadrul vectorului si se returneaza -1.

Această problemă nu mai necesită analiza tuturor subproblemelor în care se descompune, ea se


reduce la o singură subproblemă, iar partea de combinare a soluțiilor dispare. În linii mari, această
rezolvare este tot de tip "divide et impera".
#include <iostream>
using namespace std;

int v[100], n, x;
int cautare(int st, int dr)
{int mij;
if(st<dr)
{mij =(st+dr)/2;
if (x==v[mij])
return 1;
else
if (x<v[mij])
cautare(st, mij-1);
else cautare(mij+1, dr);
}
else
return -1;
}

int main( )
{
cout<<"n="; cin>>n;
for (int i=1; i<=n; i++)
{
cout<<"v["<<i<<"]="; cin>>v[i];
}
cout<<"x="; cin>>x;
cout<<cautare (1,n);
return 0;
}

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