Sunteți pe pagina 1din 4

Divide et impera

Divide et impera se bazeaz pe principiul descompunerii problemei n dou sau mai multe
subprobleme (mai uoare), care se rezolv, iar soluia pentru problema iniial se obine combinnd
soluiile subproblemelor. De multe ori, subproblemele sunt de acelai tip i pentru fiecare din ele se
poate aplica aceeai tactic a descompunerii n (alte) subprobleme, pn cnd (n urma
descompunerilor repetate) se ajunge la probleme care admit rezolvare imediat.
Nu toate problemele pot fi rezolvate prin utilizarea acestei tehnici. Se poate afirma c numrul celor
rezolvabile prin "divide et impera" este relativ mic, tocmai datorit cerinei ca problema s admit o
descompunere repetat.
Divide et impera este o tehnic ce admite o implementare recursiv. Principiul general prin care se
elaboreaz algoritmi recursivi este: "ce se ntmpl la un nivel, se ntmpl la orice nivel" (avnd grij
s asigurm condiiile de terminare). Aadar, un algoritm prin divide et impera se elaboreaz astfel:
la un anumit nivel avem dou posibiliti:
1. s-a ajuns la o problem care admite o rezolvare imediat (condiia de terminare), caz n care
se rezolv i se revine din apel;
2. nu s-a ajuns n situaia de la punctul 1, caz n care problema curent este descompus n
(dou sau mai multe) subprobleme, pentru fiecare din ele urmeaz un apel recursiv al
funciei, dup care combinarea rezultatelor are loc fie pentru fiecare subproblem, fie la
final, naintea revenirii din apel.
Aplicaii
Maximul dintr-un vector
Se citete un vector cu n componente, numere naturale. Se cere s se tipreasc valoarea maxim.

Funcia cutat va genera valoarea maxim dintre numerele reinute n vector pe o poziie dintre i i j
(iniial, i=1, j=n). Pentru aceasta, se procedeaz astfel:

dac i=j, valoarea maxima va fi v*i+;
n caz contrar, se imparte vectorul n doi subvectori - presupunem varianta pentru
paralelizare pe 2 procesoare. Se calculeaz mijlocul m al intervalului *i, j+: m = (i+j) div 2.
Primul subvector va conine componentele de la i la m, al doilea va conine componentele de
la (m+1) la j; se rezolv subproblemele (aflndu-se astfel maximul pentru fiecare din
subvectori), iar soluia curent va fi dat de valoarea maxim dintre rezultatele celor dou
subprobleme.
#include <iostream>
using namespace std;
int v[10],n;

int max(int i, int j)
{
int a, b, m;
if (i==j) return v[i];
else
{
m = (i+j)/2;
a = max(i, m);
b = max(m+1, j);
if (a>b) return a;
else return b;
}
}

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


Cutare binar
Se citete un vector cu n componente numere ntregi (numerele se presupun ordonate cresctor) i o
valoare ntreag ("nr"). S se decid dac nr se gsete sau nu printre numerele citite, iar n caz
afirmativ s se tipreasc indicele componentei care conine aceast valoare.

O rezolvare n care nr se compar pe rnd cu toate cele n componente reperzint o pierdere de
performan (nu exploateaz faptul c cele n valori sunt n secven cresctoare). Algoritmul care va
fi propus este optim i se poate spune c face parte dintre algoritmii "clasici".

Funcia care va fi implementat va decide dac valoarea cutat se gsete printre numerele aflate
pe poziii de indice cuprins ntre i i j (iniial, i=1, j=n). Pentru aceasta, se va proceda astfel:
dac nr coincide cu valoarea de la mijloc, aflat pe poziia de indice (i+j)/2, se tiprete
indicele i se revine din apel (problema a fost rezolvat).
n caz contrar, dac mai sunt i alte elemente de analizat (adic i<j, deci nu au fost verificate
toate poziiile necesare), problema se descompune astfel:
1. dac nr este mai mic dect valoarea testat (din mijloc), nseamn c nu se poate afla pe
poziiile din partea dreapt, ntruct acestea sunt cel puin mai mari dect valoarea
testat. Nr se poate gsi doar printre componentele cu indice ntre i i (i+j)/2 - 1, caz n
care se reapeleaz funcia cu aceti parametri;
2. dac nr este mai mare dect valoarea testat (din mijloc), nseamn c nu se poate afla n
stnga; se poate gsi doar printre componentele cu indicele ntre (i+j)/2 + 1 i j, caz n
care se reapeleaz funcia cu aceti parametri.
dac nu mai sunt alte elemente de analizat (pentru c i=j i valoarea din mijloc, v*i+, nu
coincide cu nr), se concluzioneaz c nr nu apare n cadrul vectorului.
Aceast problem nu mai necesit analiza tuturor subproblemelor n care se descompune, ea se
reduce la o singur subproblem, iar partea de combinare a soluiilor dispare. n linii mari, aceast
rezolvare este tot de tip "divide et impera".
#include <iostream>
using namespace std;

int v[100], n, nr;
void caut(int i, int j)
{
int m = (i+j)/2;
if (nr==v[m])
cout<<"gasit, indice="<<m;
else
if (i<j)
if (nr<v[m])
caut(i, m-1);
else caut(m+1, j);
else cout<<"nu a fost gasit.";
}

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

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