Documente Academic
Documente Profesional
Documente Cultură
Divide Et Impera
Divide Et Impera
Divide et impera se bazează pe principiul descompunerii problemei în două sau mai multe
subprobleme (mai ușoare), care se rezolvă, iar soluția pentru problema inițială se obține
combinând soluțiile subproblemelor. De multe ori, subproblemele sunt de același tip și pentru
fiecare din ele se poate aplica aceeași tactică a descompunerii în (alte) subprobleme, până când
(î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ă numărul
celor rezolvabile prin "divide et impera" este relativ mic, tocmai datorită cerinței 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 întâmplă la un nivel, se întâmplă la orice nivel"
(având grijă să asigurăm condițiile de terminare). Așadar, un algoritm prin divide et impera se
elaborează astfel: la un anumit nivel avem două posibilități:
1. s-a ajuns la o problemă care admite o rezolvare imediată (condiția de terminare), caz în
care se rezolvă și se revine din apel;
2. nu s-a ajuns în situația 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
funcției, după care combinarea rezultatelor are loc fie pentru fiecare subproblemă, fie la
final, înaintea revenirii din apel.
Aplicații
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 i
și j (inițial, i=1, j=n). Pentru aceasta, se procedează astfel:
#include <iostream>
using namespace std;
int v[10],n;
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;
}
Căutare binară
Se citește un vector cu n componente numere întregi (numerele se presupun ordonate crescător)
și o valoare întreagă ("nr"). Să se decidă dacă nr se găsește sau nu printre numerele citite, iar în
caz afirmativ să se tipărească indicele componentei care conține această valoare.
O rezolvare în care nr 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 i și j (inițial, i=1, j=n). Pentru aceasta, se va proceda astfel:
dacă nr 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 testată. Nr se poate găsi doar printre componentele cu indice între i și (i+j)/2
- 1, caz în care se reapelează funcția cu acești parametri;
dacă nr 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 (i+j)/2 + 1 și
j, caz în care se reapelează funcția cu acești 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 soluțiilor dispare. În linii
mari, această rezolvare este tot de tip "divide et impera".
#include <iostream>
using namespace std;
int v[100], n, nr;
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;
}