Sunteți pe pagina 1din 20

Metoda

programării
dinamice
Tipul problemelor rezolvabile prin tehnica
programării dinamice
●Programarea dinamică este o metodă de
rezolvare a unor probleme în care se cere de regulă
determinarea unei valori maxime sau minime, sau
numărarea elementelor unei mulțimi.

● Programarea dinamică este o metodă de


rezolvare a problemelor, care conduce la o soluţie
optimă într-un timp de calcul de ordin polinomial.
Cine a introdus termenul de PD?

Inițiatorul acestei metode este profesorul


Richard Bellman care a publicat în 1957 o
carte cu titlul “Dynamic programming”,
introducând astfel pentru prima data conceptul
de PD (programare dinamică).
Ce este metoda programării dinamice?
Metoda programării dinamice
- este o tehnică de proiectare al algoritmilor pentru rezolvarea
problemelor care pot fi descompuse în subprobleme care se suprapun.
- poate fi aplicată problemelor de optimizare care au proprietatea
de substructură optimă.
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.
Metoda programării dinamice se
aplică problemelor a căror soluție se
poate construi dinamic în timp, adică
deciziile care conduc la obținerea
rezultatului se pot lua pas cu pas, pe baza
deciziilor de la pasul / pașii precedenți.
Metoda PD se poate aplica cu
următoarele abordări:

Metoda înainte Metoda înapoi Metoda mixtă


• Pentru rezolvarea • Pentru rezolvarea • O combinaţie
problemei se pleacă de la problemei se pleacă a primelor două,
starea finală. de la starea iniţială. metoda înainte și
metoda înapoi.
În problemele care pot fi rezolvate utilizând PD
identificăm două proprietăți:

Substructura Subprobleme
optimală superpozabile
• Problema poate fi descompusă in • Subproblemele nu sunt
subprobleme, iar soluțiile optime ale independente, ci se suprapun.
subproblemelor determină soluția optimă a Soluțiile subproblemelor se vor
problemei inițiale (în acest caz s-ar putea aplica reține într-un tablou (vector sau
și una dintre metodele Greedy sau Divide-et- matrice).
Impera).
Etapele rezolvării unei probleme utilizând
metoda programării dinamice
Problemă:
Problemă:
Se dă o scară cu N trepte. Un individ se află în partea de jos a
scării și poate să urce câte o treaptă la un pas, sau câte două trepte
la un pas. În câte moduri poate urca scara?

Explicație: Observăm că dacă scara are o treaptă, ea poate fi


urcată într-un singur mod, iar dacă are două trepte, sunt
două modalități de a urca scara: doi pași de o treaptă sau
un un pas de două trepte. Pentru N=4, scara poate fi
urcată în 5 moduri:

• 1111
• 112
• 121
• 211
• 22
Rezolvare:
Este problemă de numărare; dacă numerotăm treptele, observăm că pe treapta N se poate ajunge
de pe treapta N-1 (cu un pas de o treaptă) sau de pe treapta N-2 (cu un pas de două trepte),
cazurile N=1 și N=2 fiind particulare.
Atunci, numărul de variate de a urca N trepte este egal cu numărul de variante de a urca N-1
trepte, plus numărul de variante de a urca N-2 trepte. Deducem deci următoarea relație de
recurență, în care T(n) reprezintă numărul de modalități de a urca o scară cu n trepte:

Constatăm că formula anterioară respectă proprietățile descrise mai sus pentru probleme
rezolvabile prin programare dinamică: subprobleme de același tip, de dimensiuni mai mici și care
se suprapun; în determinarea lui T(n) intervine T(n−1) și T(n−2). În determinarea lui T(n−1)
apare din nou T(n−2), ș.a.m.d., situație care face ca utilizarea recursivității să fie foarte
ineficientă.
De fapt, putem observa că formula de mai sus este de fapt definiția șirului lui Fibonacci, despre
care am văzut deja că are o soluție de complexitate O(n), construind termenii în ordine
crescătoare, folosind eventual un tablou unidimensional (sau doar trei variabile simple).
●Odată identificată relația de recurență, este necesară stabilirea unui algoritm de rezolvare
a recurenței. Datorită suprapunerii subproblemelor, utilizarea recursivității este foarte
neeficientă. De regulă se folosește o structură de date suplimentară – tablou unidimensional,
bidimensional sau cu mai multe dimensiuni (în funcție de numărul variabilelor care intervin
în relația de recurență).
●Soluția problemei se află într-un element al tabloului sau se poate determina folosind o
parte a elementelor acestuia. Elementele tabloului se vor determina unul câte unul, până când
sunt determinate toate elementele necesare pentru aflarea soluției!
●Pentru problema scării, notăm tabloul necesar cu V[]. Este un tablou unidimensional
deoarece în relația de recurență apare o singură variabilă (n); formula recursivă devine:
V[1] = 1, V[2]=2;
V[n] = V[n-1] + V[n-2], pentru n>2;

○ Inițializăm primele două elemente ale tabloului, iar celelalte elemente vor fi
construite unul după altul, de la stânga spre dreapta. Rezultatul se va găsi în V[n].
Program C++: Afișarea rezultatului:
Explicație:

Conform problemei anterioare,


s-a creat o funcție, având ca
parametru N, care a trecut prin
catevă procese decizionale, iar
pentru cazul în care condiția
decizională ‘IF’, a fost ‘TRUE’,
s-a executat și s-a returnat
rezultatul.
Concluzie

● o problemă se rezolvă prin metoda programării dinamice dacă se poate


descompune în subprobleme superpozabile și care respectă principiul
optimalității;
● se identifică relația de recurență pentru subprobleme și structura de date
ajutătoare;
● se rezolvă recurența, folosind metoda bottom-up sau top-down.
Problemă
●Se consideră un triunghi de numere naturale format din n linii. Prima linie conține un
număr, a doua linie conține 2 numere, etc. ultima linie n, conține n numere. În acest triunghi
se pot calcula diverse sume cu n elemente, astfel:
○ termenul i al sumei se află pe linia i din triunghi.
○ pentru un anumit termen al sumei, termenul următor se află pe linia următoare și
pe aceeași coloană, sau pe coloana imediat următoare spre dreapta.
● Să se determine cea mai mare sumă care se poate obține în acest mod.
Fişierul de intrare sumtri.in conţine pe prima linie numărul n(1 ≤ n ≤ 100). Fiecare dintre
următoarele n linii conține câte o linie a triunghiului. (numerele din triunghi sunt mai mici decât 1000)
5
Date de ieșire
4
Fişierul de ieşire sumtri.out va conţine pe
14
prima linie numărul S, reprezentând cea
213
mai mare sumă care se poate obține.
9443
45221
Analiza problemei
Program C++:
Bibliografie
● https://sites.google.com/site/abcinfoliceu/metode-de/metoda-programarii-dinamice
● http://ler.is.edu.ro/~cex_is/Informatica/2012/teme/10/t9.pdf
● https://www.pbinfo.ro/articole/17951/programare-dinamica-introducere
● https://problemeatestat.weebly.com
Sfârșit

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