Sunteți pe pagina 1din 4

METODA PROGRAMĂRII DINAMICE

Programarea dinamică este o tehnică de proiectare a algoritmilor pentru


rezolvarea problemelor în care trebuie să fie găsită soluția optimă și care pot fi descompuse în
subprobleme similare cu problema inițială care se suprapun (nu sunt independente ca la metoda
„Divide et Impera”).
Particularitatea metodei constă în faptul că fiecare suproblemă este rezolvată o singură dată
iar soluția ei este stocată (într-o structură tabelară) pentru a putea fi ulterior folosită
pentru rezolvarea problemei inițiale. 
In programarea dinamică cuvântul programare se referă la planificare și nu la programare
în sens informatic. Cuvântul dinamic se referă la maniera în care sunt construite tabelele în care
se rețin informațiile referitoare la soluțiile parțiale.
Programarea dinamică reprezintă o metodă de rezolvare a unor probleme complexe prin
descompunerea lor în subprobleme mai simple. Această metodă se aplică problemelor care: 
- admit o formulare recursivă 
- pot fi descompuse în subprobleme similare cu problema inițială
- soluţiile subproblemelor se suprapun (nu sunt independente ca la metoda „Divide et
impera”) 
- subproblemele admit o soluţie obţinută printr-un criteriu de optimizare
Ideea pe care se bazează programarea dinamică este asemănătoare cu cea de la metoda
divide et impera: pentru a găsi soluţia unei probleme generale, trebuie să rezolvăm o serie de
subprobleme (părţi), iar apoi să combinăm rezultatele parţiale (ale subproblemelor) pentru a
ajunge la soluţia globală. Subproblemele care trebuie rezolvate au aceaşi structură, adică pot fi
formulate recursiv.
Abordarea folosită în programarea dinamică este aceea de a rezolva fiecare subproblemă o
singura data, reducând astfel numărul de operaţii necesare – o dată ce un rezultat parţial a
fost calculat, acesta este memorat într-o structură de date. Această tehnică poartă denumirea de
memorizare.
Dacă acelaşi rezultat parţial este folosit de mai multe ori în obţinerea soluţiei globale este
luat direct din structura de date în care a fost memorat, reducând complexitatea calculelor din
algoritm. Reducerea complexităţii de calcul se face prin folosirea în schimb a unui volum mai
mare de memorie, necesar pentru memorarea tuturor acestor rezultate parţiale. 
Structurile de date folosite în programarea dinamică sunt tablourile uni sau bidimensionale
(matrici).
Programarea dinamica este coreleta si cu strategia cautarii locale optime, (greedy) intrucat
ambele se aplica problemelor de optimizare care au proprietatea de substructura optima.
Etapele rezolvării unei probleme utilizând metoda programării dinamice
1. identificarea subproblemelor
2. alegerea unei structuri care să reţină soluţiile subproblemelor
3. determinarea unei relaţii de recurenţă care să caracterizeze substructura optimală
(dependenţa soluţiei subproblemei curente de soluţiile subproblemelor în care se descompune)
4. rezolvarea recurenţei în mod bottom-up (în ordinea crescătoare a dimensiunilor
subproblemelor) pentru determinarea soluţiei optime a problemei iniţiale

Exemplu: problema triunghiului.


Se considera un triunghi de numere naturale cu n linii. Pe prima linie se afla un numar, pe a
doua linie - doua numere, s.a.m.d. Pornind de la prima linie, mergand in jos pana la linia n, sa
selecteze, de pe fiecare linie cate un element astfel incat suma lor sa fie maxima. Trecerea la linia
următoare se face doar mergând în jos pe aceeași coloană sau pe diagonală la dreapta.

Mod de rezolvare:

1. Descompunerea pb în subprobleme: Se determină, pe rând, suma maximă a numerelor


ce apar pe traseele care pornesc de pe ultima linie n către vârf și ajung pe linia i (1<=i<=n). Pe
linia i suma maximă pentru fiecare element se va calcula pe baza sumelor maxime care s-au
calculat în subproblemele anterioare (sumele de la linia n până la linia i+1)
2. Alegerea structurilor:
Pentru memorarea elementelor triunghiului se va folosi o matrice a de ordin n inferior
triunghiulară.
Pentru memorarea sumelor maxime ale subproblemelor se va folosi o matrice s de ordin n
inferior triunghiulară, un element s[i][j] memorând maximul sumelor elementelor din triunghiul
de numere cu vârful în i (în deplasare respectându-se direcția de mers).
3. Relația de recurență care definește suma maxima pentru o subproblemă este:
a [ i ][ j ] pentru i=n ; ∀ j=1, i
{
s [ i ] [ j]=
a [ i ] [ j ] +max ⁡(s [ i+1 ][ j ] , s [ i+1 ][ j+1 ] , ∀ i=1 ,n−1)
4. Rezolvarea recurenţei în mod bottom-up pentru determinarea soluţiei optime a
problemei iniţiale

Exemplu: fie n=4 și matricea a:


5 0 0 0
4 2 0 0
5 4 3 0
4 6 2 5

Completând matricea s de la linia 4 la linia 1, vom obține:


5+15=2 0 0 0
0
4+11=1 2+10=14 0 0
5
5+6=11 4+6=10 3+5=8 0
4 6 2 5
Deci, suma maxima este 20

Exemplul 2: fie n=5 și matricea a:


3 0 0 0 0
4 6 0 0 0
5 4 1 0 0
1 4 2 6 0
6 1 4 3 2
Scrieți matricea s obținută și evidențiați numerele adunate pentru obținerea sumei maxime
#include<iostream>
using namespace std;

int a[50][50],s[50][50],drum[50][50],n,i,j;

void citire() // se citesc elementele triunghilui


{cout<<"nr. linii:";cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
{cout<<"a["<<i<<","<<j<<"]";
cin>>a[i][j];
}
}

void init()
{for(int j=1;j<=n;j++) // se initializeaza linia n a matricii solutiei cu linia n a matricii a
s[n][j]=a[n][j];}

void triunghi() // se calculeaza in matricea s solutiile subproblemelor si in matricea d


drumul ales
{for(int i=n-1;i>=1;i--)
for(int j=1;j<=i;j++)
if(s[i+1][j]<s[i+1][j+1])
{s[i][j]=a[i][j]+s[i+1][j+1];
drum[i][j]=j+1;
}
else
{s[i][j]=a[i][j]+s[i+1][j];
drum[i][j]=j;
}
}

void afisare()
{cout<<"suma maxima="<<s[1][1]<<endl;
cout<<"elementel parcurse:";
i=1;
j=1;
while(i<=n)
{cout<<a[i][j]<<" ";
j=drum[i][j];
i++;
}
}
int main()
{ citire();
init();
triunghi();
afisare();
}

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