Programarea dinamica

10

description

Informatica

Transcript of Programarea dinamica

Page 1: Programarea dinamica
Page 2: Programarea dinamica

PROGRAMAREA DINAMICA

Programarea dinamica face parte dintr-o categorie de metode matematice numite metode de scufundare. O problema de programare dinamica contine subprobleme comune (care nu sunt independente) din a caror rezolvare si combinare se obtine solutia unei probleme mai mari. Deci rezolvarea unei probleme se poate face doar dupã solutionarea (sub)problemelor, care alcatuiesc problema respectiva. Spunem ca programarea dinamica actioneaza de jos in sus, prelucrand si combinand subcazuri mici, obtinand astfel solutia pentru subcazuri tot mai mari.

Page 3: Programarea dinamica

Totodata programarea dinamica evita rezolvarea de mai multor ori a aceleiasi subprobleme (rezolvandu-se doar problemele independente ), prin memorarea rezultatelor partiale.

Nu exista un criteriu pe baza caruia sa identificam cu siguranta o problema pentru rezolvarea careia trebuie sa utilizam metoda programarii dinamice, dar putem formula doua proprietati care sugerează o solutie prin programare dinamica.

Page 4: Programarea dinamica

PRINCIPII FUNDAMENTALE ALE PROGRAMARII DINAMICE

Programarea dinamica, ca si metoda divide et impera, rezolva problemele combinand solutiile subproblemelor. Dupa cum am vazut, algoritmii divide et impera partitioneaza problemele in subprobleme independente, rezolva subproblemele in mod recursiv, iar apoi combina solutiile lor pentru a rezolva problema initiala. Daca subproblemele contin subsubprobleme comune, in locul metodei divide et impera este mai avantajos de aplicat tehnica programarii dinamice.

Page 5: Programarea dinamica

Sa analizam insa pentru inceput ce se intampla cu un algoritm divide et impera in aceasta din urma situatie. Descompunerea recursiva a cazurilor in subcazuri ale aceleiasi probleme, care sunt apoi rezolvate in mod independent, poate duce uneori la calcularea de mai multe ori a aceluiasi subcaz, si deci, la o eficienta scazuta a algoritmului.

Page 6: Programarea dinamica

Primul principiu de baza al programarii dinamice: evitarea calcularii de mai multe ori a aceluiasi subcaz, prin memorarea rezultatelor intermediare.

Al doilea principiu fundamental al programarii dinamice este faptul ca ea opereaza de jos in sus Se porneste de obicei de la cele mai mici subcazuri. Combinand solutiile lor, se obtin solutii pentru subcazuri din ce in ce mai mari, pina se ajunge, in final, la solutia cazului initial.

Page 7: Programarea dinamica

al treilea principiu fundamental, programarea dinamica este utilizata pentru a optimiza o problema care satisface principiul optimalitatii: intr-o secventa optima de decizii sau alegeri, fiecare subsecventa trebuie sa fie de asemenea optima. Cu toate ca pare evident, acest principiu nu este intotdeauna valabil si aceasta se intampla atunci cand subsecventele nu sunt independente, adica atunci cand optimizarea unei secvente intra in conflict cu optimizarea celorlalte subsecvente.

Page 8: Programarea dinamica

Aplicatie

Fie un sir de n numere naturale. Se cere sa se gaseasca cel mai lung subsir crescator al sau.

Exemplu: şirul {2, 4, 3, 5, 3, 6} are cel mai lung subsir crescator de lungime 4: {2, 4, 5, 6} sau {2, 3, 5, 6}.

Rezolvare:

Soluţia problemei nu este unică, dar lungimea maximă a subşirului crescător, da.

Vom nota cu L[k] lungimea celui mai lung subşir crescător care începe de la poziţia k şi până la sfârşitul şirului iniţial. Calculăm, pe rând, L[n], L[n-1], L[n-2] … L[2], L[1]. Lungimea celui mai lung subşir crescător va fi dată de cea mai mare valoare a lui L.

L[n] = 1

L[k] = 1+ max {L[i ], unde k<i≤n şi v[k]≤v[i ]}, k=n-1,1

#include<fstream.h>

int v[10000],n,i,L[1000],max,mx,k,t;

Page 9: Programarea dinamica

Aplicatie (continuare)

int main(){

fstream f("subsir.txt",ios::in);

for(i=1;i<=n;i++) f>>v[i];

L[n]=1; //subsir maxim de lung 1

for(k=n-1;k>0;k--)

{mx=0;

for(i=k+1;i<=n;i++)

if(v[i]>=v[k] && L[i]>mx)

mx=L[i];

L[k]=mx+1;

if(L[k]>max)

{max=L[k];

t=k;}

}

Page 10: Programarea dinamica

Aplicatie (continuare)

cout<<"lungimea maxima:"<<max;

//afisarea subsirului

cout<<endl<<v[t]<<' ';

for(i=t+1;i<=n;i++)

if ((v[i]>=v[t]) && (L[i]==max-1))

{cout<<v[i]<<' ';

max--;}

return 0;

}