Sunteți pe pagina 1din 4

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.

Prezentare general:
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:

s-a ajuns la o problem care admite o rezolvare imediat (condiia de terminare), caz
n care se rezolv i se revine din apel;
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:
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;
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