Upload
maglasu-ionut
View
287
Download
6
Embed Size (px)
DESCRIPTION
prezentare
Citation preview
Programare dinamic 1 1 1
Metoda programrii dinamice
Prof. Emanuela Cerchez
Liceul de Informatica Grigore Moisil Iasi
Prezentare general
Programarea dinamic este o metod de elaborare a algoritmilor care se aplic n general problemelor pentru care se cere determinarea unui optim n urma
adoptrii unor decizii.
Nu exist un criteriu pe baza cruia s identificm cu siguran o problem pentru rezolvarea creia trebuie s utilizm metoda programrii dinamice, dar putem formula dou proprieti care sugereaz o soluie prin programare dinamic.
Substructur optimal
Problema dat poate fi descompus n subprobleme i soluia optim a problemei depinde de soluiile optime ale subproblemelor sale.
Acest criteriu nu indic neaprat o soluie prin programare dinamic, ar putea fi i un indiciu c se poate aplica metoda Greedy sau metoda Divide et Impera.
Subprobleme superpozabile
Subproblemele problemei date nu sunt independente, ci se suprapun.
Datorit faptului c subproblemele problemei date se suprapun, deducem c o abordare prin metoda Divide et Impera ar fi dezastruoas din punctul de vedere al timpului de execuie (datorit faptului c problemele se suprapun se ajunge la rezolvarea repetat a aceleiai subprobleme). Prin urmare, vom rezolva subproblemele o singur, dat, reinnd rezultatele ntr-o structur de date suplimentar (de obicei un tablou).
Rezolvarea unei probleme prin programare dinamic presupune urmtorii pai:
1. Se identific subproblemele problemei date.
2. Se alege o structur de date suplimentar, capabil s rein soluiile subproblemelor.
3. Se caracterizeaz substructura optimal a problemei printr-o relaie de recuren.
4. Pentru a determina soluia optim, se rezolv relaia de recuren n mod bottom-up (se rezolv subproblemele n ordinea cresctoare a dimensiunii lor).
n cele ce urmeaz vom exemplifica pas cu pas modul de rezolvare a problemelor prin metoda programrii dinamice.
2 METODA PROGRAMRII DINAMICE
1. nmulirea optimal a matricelor
Fie n matrice A1, A2, ..., An, de dimensiuni d0xd1, d1xd2, ..., dn-1xdn. Produsul
A1xA2x...xAn se poate calcula n diverse moduri, aplicnd asociativitatea
operaiei de nmulire a matricelor. Numim nmulire elementar nmulirea a dou elemente. n funcie de modul de parantezare difer numrul de nmuliri
elementare necesare pentru calculul produsului A1xA2x...xAn. Determinai o
parantezare optimal a produsului A1xA2x...xAn (costul parantezrii, adic numrul total de nmuliri elementare s fie minim).
Exemplu
Pentru n=3 matrice cu dimensiunile (10,1000), (1000,10) i
(10,100), produsul A1xA2xA3 se poate calcula n dou moduri:
1. (A1xA2)xA3 necesitnd 1000000+10000=1010000 nmuliri elementare
2. A1x(A2xA3), necesitnd 1000000+1000000=2000000 nmuliri.
Reamintim c numrul de nmuliri elementare necesare pentru a nmuli o
matrice A cu n linii i m coloane i B o matrice cu m linii i p coloane este nmp
(vezi problema 8 de la capitolul Structuri elementare de date).
Solutie
1. Pentru a calcula A1xA2x...xAn, n final trebuie s nmulim dou matrice, deci
vom paranteza produsul astfel: (A1xA2x...xAk)x(Ak+1x...xAn ). Aceast observaie se aplic i produselor dintre paranteze. Prin urmare, subproblemele problemei iniiale constau n determinarea parantezrii optimale a produselor de
matrice de forma AixAi+1x...xAj, 1ijn. Observm c subproblemele nu
sunt independente. De exemplu, calcularea produsului AixAi+1x...xAj i
calcularea produsului Ai+1xAi+2x...xAj+1, au ca subproblem comun
calcularea produsului Ai+1x...xAj.
2. Pentru a reine soluiile subproblemelor, vom utiliza o matrice M, cu n linii i n coloane, cu semnificaia:
M[i][j] = numrul minim de nmuliri elementare necesare pentru a calcula
produsul AixAi+1x...xAj, 1ijn.
Evident, numrul minim de nmuliri necesare pentru a calcula A1xA2x...xAn
este M[1][n].
3. Pentru ca parantezarea s fie optimal, parantezarea produselor A1xA2x...xAk
i Ak+1x...xAn trebuie s fie de asemenea optimal. Prin urmare elementele
matricei M trebuie s satisfac urmtoarea relaie de recuren:
M[i][i]=0, i{1,2,..., n}. M[i][j]=min{M[i][k] + M[k+1][j] + d[i-1]*d[k]*d[j]}
ik
Programare dinamic 3 1 1
Cum interpretm aceast relaie de recuren? Pentru a determina numrul
minim de nmuliri elementare pentru calculul produsului AixAi+1x...xAj,
fixm poziia de parantezare k n toate modurile posibile (ntre i i j-1), i
alegem varianta care ne conduce la minim. Pentru o poziie k fixat, costul
parantezrii este egal cu numrul de nmuliri elementare necesare pentru
calculul produsului AixAi+1x...xAk, la care se adaug numrul de nmuliri
elementare necesare pentru calculul produsului Ak+1x...xAj i costul
nmulirii celor dou matrice rezultate (di-1dkdj).
Observm c numai jumtatea de deasupra diagonalei principale din M este
utilizat. Pentru a construi soluia optim este util i reinerea indicelui k, pentru care se obine minimul. Nu vom considera un alt tablou, ci-l vom reine,
pe poziia simetric fa de diagonala principal (M[j][i]).
4. Rezolvarea recursiv a relaiei de recuren de mai sus este ineficient, datorit faptului c subproblemele de suprapun, deci o abordare recursiv ar conduce la rezolvarea aceleiai subprobleme de mai multe ori. Prin urmare vom rezolva relaia de recuren n mod bottom-up: (determinm parantezarea optimal a produselor de dou matrice, apoi de 3 matrice, 4 matrice, etc).
long M[NMax][NMax];
void dinamic()
{ int nr, i, j, k, kmin;
long min, Infinit=1000000000;
for (nr=2; nr
4 METODA PROGRAMRII DINAMICE
2. Subir cresctor maximal
Fie un ir A=(a1, a2, ..., an). Numim subir al irului A o succesiune de
elemente din A, n ordinea n care acestea apar n A: ai1, ai
2, ..., ai
k, unde
1i1
Programare dinamic 5 1 1
Pentru a determina soluia optim a problemei, determinm maximul din
vectorul l, apoi afim soluia, ncepnd cu poziia maximului i utiliznd
informaiile memorate n vectorul poz:
//determin maximul din vectorul l
int max=l[1], pozmax=1;
for (int i=2; i
6 METODA PROGRAMRII DINAMICE
S[i][j]=T[i][j]+max{S[i+1][j], S[i+1][j+1]}
4. Rezolvm relaia de recuren n mod bottom-up:
int i, j;
for (i=1; i0; i--)
for (j=1; j
Programare dinamic 7 1 1
lcs[k][h]=1+lcs[k-1][h-1], dac x[k]=y[h]
max{lcs[k][h-1], lcs[k-1][h]}, dac x[k]y[h] 4. Rezolvm relaia de recuren n mod bottom-up:
for (int k=1; k
8 METODA PROGRAMRII DINAMICE
Soluie
Vom reine culorile jetoanelor ntr-un vector c[]. Iniializarea configuraiei de joc const din citirea numrului de jetoane i generarea aleatoare a culorilor
acestora, codificnd prima culoare cu 0 i cea de a doua culoare cu 1.
#define NMax 1002
int n, c[NMax];
void Init()
{coutn;
randomize();
for (int i=1; i
Programare dinamic 9 1 1
//Ana ia jetoanele de la i la k
cout
10 METODA PROGRAMRII DINAMICE
Date de ieire
Fiierul text LASER.OUT conine pe o singur linie numrul natural T.
Exemplu LASER.IN LASER.OUT
3 5
1 1 1 1 5
1 7 1 1 1
1 1 1 6 1
52
Restricii m,nN, 2m,n20
dxyN, 1dxy100
Soluie 1. Subproblemele problemei date constau n tierea unui dreptunghi din placa dat,
care are colul stnga-sus n poziia (i, j), are lungimea l i nlimea h.
2. Pentru a reine soluiile subproblemelor trebuie s utilizm un tablou cu 4
dimensiuni Cnxmxnxm, cu semnificaia C[i,j,h,l]=costul total de tiere a unui
unui dreptunghi din placa dat, care are colul stnga-sus n poziia (i, j), are
lungimea l i nlimea h. Evident, soluia problemei date va fi C[1,1,n,m].
Deoarece nu avem spaiu suficient, vom aloca parial tabloul c n mod dinamic,
i l vom iniializa cu 0:
int i, j, k, l, h;
for (i=0; i
Programare dinamic 11 1 1
Prin urmare putem caracteriza substructura optimal a problemei prin urmtoarea relaie de recuren:
C[i][j][1][1]=0; i{1,2,..,n}, j{1,2,..,m} C[i][j][h][l]=min
{min{c[i][j][k-i][l]+c[k][j][h-k+i][l]+dmaxL(k,j,l)}//orizontal k=i+1,i+h-1
min{c[i][j][h][k-j]+c[i][k][h][l-k+j]+dmaxC(k,i,h)}} //vertical k=j+1,j+l-1
n relaiile de recuren precedente am utilizat valorile:
dmaxL(k,j,l), reprezentnd densitatea maxim a bucilor 11 peste
marginile crora trece raza laserului, la o tietur ntre liniile k-1 i k, de
lungime l, ncepnd de la coloana j;
dmaxC(k,i,h), reprezentnd densitatea maxim a bucilor 11 peste
marginile crora trece raza laserului, la o tietur ntre coloanele k-1 i k,
de lungime h, ncepnd cu linia i.
4. Calculul soluiei optime n mod bottom-up:
for (h=1; h
12 METODA PROGRAMRII DINAMICE
Observaie O optimizare posibil a algoritmului const n evitarea apelurilor funciilor
dmaxL() i dmaxC(), prin precalcularea valorilor respective o singur dat i memorarea lor n cte un tablou tridimensional. Implementai aceast optimizare!
7. Problema patronului
Un patron de gogoerie a cumprat un calculator i dorete s nvee s lucreze pe el. Pentru aceasta va umple un raft de cri din colecia Informatica n lecii de
9 minute i 60 secunde. Raftul are lungimea L cm. Seria dispune de n titluri,
numerotate 1, 2,..., n avnd respectiv grosimile de g1, g2,..., gn cm.
Scriei un program care s selecteze titlurile pe care le va cumpra patronul, astfel nct raftul s fie umplut complet (suma grosimilor crilor cumprate s fie egal cu lungimea raftului) i numrul crilor achiziionate s fie maxim. Progra-mul va afia numrul crilor selectate, precum i grosimile acestora. Dac nu
exist soluie, va fi afiat mesajul IMPOSIBIL. (ONI Suceava 1996, XI)
Restricii nN, 1n60
LN,1L200
giN*, gi30000, i{1,2,...,n}
Timp maxim de execuie: 1 secund/test.
Exemplu
Soluie
1. Problema const n selectarea unor elemente a cror sum s fie egal cu L. n
cazul n care exist mai multe soluii, este preferat soluia cu numr maxim de elemente. O subproblem a acestei probleme const n selectarea unor elemente
a cror sum s fie egal cu S, SL.
2. Pentru a reine soluiile subproblemelor vom utiliza un vector Nr, cu L+1
componente, avnd semnificaia: Nr[S]=numrul maxim de titluri ce pot fi
cumprate pentru a umple un raft de lungime S (0SL) sau -1 (dac nu putem
umple un raft de lungime S). Pentru a reine i crile cumprate, vom utiliza o
matrice Uz cu L+1 linii i n coloane, avnd semnificaia L[S][i] este 1, dac
am utilizat titlul i pentru a umple optimal raftul de lungime S i 0, n caz contrar.
#define NMax 61
#define LMax 201
int n, L; //numarul de titluri si lungimea raftului
int g[NMax]; //grosimile
int Nr[LMax]; //numarul maxim de carti selectate
int Uz[LMax][NMax]; //indicii titlurilor utilizate
Programare dinamic 13 1 1
3. S considerm c ultimul titlu selectat pentru a umple un raft de lungime S este
i. Prin urmare, n rest sunt selectate (obligatoriu n mod optim) cri a cror
grosime total trebuie s fie egal cu S-g[i]. Evident, pentru a putea alege
titlul i, condiia este ca acest titlu s nu fie deja utilizat pentru a umplerea
restului raftului (de lungime S-g[i]). Alegerea titlului i trebuie s fie fcut de asemenea n mod optim (s maximizeze numrul total de cri selectate):
Nr[0]=0;
Nr[S]=max{-1, max{1+Nr[S-g[i]]|S-g[i]0 i Nr[S-g[i]]-1 i i=1,n Uz[S-g[i]][i]=0}
4. Rezolvarea relaiei de recuren:
int S, k, i;
for (S=1; S
14 METODA PROGRAMRII DINAMICE
Taste acionate Efect + urmat de o cifr Se genereaz suma dintre cifra de pe afiaj i cifra tastat (operaie
posibil doar dac suma este tot o cifr). Cifra sum este reinut n memorie.
urmat de o cifr Se genereaz diferena dintre cifra de pe afiaj i cifra tastat (operaie posibil doar dac se obine tot o cifr). Cifra obinut este reinut n memorie.
* urmat de o cifr Se reine n memorie valoarea tastei care se acioneaz dup tasta
*. Deoarece asupra cifrei curente din X nu se efectueaz nici o
operaie, aceasta nu dispare de pe afiaj. / Se terge cifra curent din X # Se terg din X cifra curent i toate cifrele care urmeaz, pn la
sfrit. = Se copiaz n memorie cifra curent.
Aciunea se ncheie atunci cnd toate cifrele lui X au fost prelucrate. Am obinut
o soluie cnd n memoria telecomenzii se afl cifrele numrului Y. O soluie este
optim dac numrul de taste acionate este minim. Ctigtorii jocului sunt acei concureni care descoper o soluie optim.
Date fiind X i Y, scriei un program care s determine o soluie optim de
transformare a numrului X n numrul Y. (ONI, Bacu 2001, XI-XII)
Date de intrare
Fiier de intrare TELE.IN conine dou linii: X
Y
Date de ieire
Fiier de ieire TELE.OUT conine dou linii: min
t1t2...tmin
unde:
min este un numr natural nenul, reprezentnd numrul minim de taste
acionate pentru transformarea lui X n Y.
t1t2...tmin este o succesiune de min caractere, care reprezint tastele acionate; ntre caractere nu se vor pune separatori.
Exemplu TELE.IN TELE.OUT
372 4
78 /=+6
Timp maxim de execuie/test: 1 secund
Soluie
1. S notm cu m numrul de cifre din X i cu n numrul de cifre din Y. De
asemenea vom nota Xi sufixul care ncepe cu cifra i din X (secvena de cifre
Programare dinamic 15 1 1
XiXi+1...Xm) i cu Yj sufixul care ncepe cu cifra j din Y (secvena de cifre
YjYj+1...Yn). Subproblemele problemei date constau n determinarea
transformrii de cost minim a lui Xi n Yj, i{1,2,...,m} i j{1,2,...,n}.
2. Pentru a reine soluiile subproblemelor vom utiliza dou matrice cm i o,
fiecare cu m linii i n coloane, avnd urmtoarea semnificaie:
cm[i][j] = numrul minim de acionri de taste necesar pentru a
transforma Xi n Yj.
o[i][j] = prima operaie ce va fi executat pentru a transforma optimal Xi
n Yj.
typedef char Operatie[3];
char x[DimMax], y[DimMax];
int cm[DimMax][DimMax];
Operatie o[DimMax][DimMax];
int n, m;
Evident, cm[1][1] reprezint numrul minim de acionri de taste necesar
pentru a transforma numrul X n numrul Y.
3. Relaia de recuren carecaracterizeaz substructura optimal a problemei este:
cm[i][j]=min
{1+cm[i+1][j], //operatia /
2+cm[i][j+1], //operatia *Y[j]
2+cm[i+1][j+1], //operatia - X[i]-Y[j], daca X[i]>Y[j]
2+cm[i+1][j+1], //operatia + Y[j]-X[i], daca X[i]
16 METODA PROGRAMRII DINAMICE
{min=1+cm[i+1][j]; strcpy(omin,"/");
if (min>2+cm[i][j+1])
{min=2+cm[i][j+1];
omin[0]='*'; omin[1]=y[j]; omin[2]=NULL;}
if (x[i]>y[j])
{if (min>2+cm[i+1][j+1])
{min=2+cm[i+1][j+1];
omin[0]='-'; omin[1]=x[i]-y[j]+'0';
omin[2]=NULL;}
}
else
if (x[i]2+cm[i+1][j+1])
{min=2+cm[i+1][j+1];
omin[0]='+'; omin[1]=y[j]-x[i]+'0';
omin[2]=NULL;}
}
else
{if (min>1+cm[i+1][j+1])
{min=1+cm[i+1][j+1]; strcpy(omin,"=");}
}
if (min>1+cm[m+1][j])
{min=1+cm[m+1][j]; strcpy(omin,"#");}
cm[i][j]=min;
strcpy(o[i][j],omin);
}
O soluie optim se obine utiliznd matricea o, a operaiilor efectuate la fiecare pas.
ofstream f("tele.out");
f
Programare dinamic 17 1 1
9. Codificare optimal
Fie un text de lungime maxim 100, ce conine doar litere. Textul poate fi
codificat, nlocuind apariiile consecutive ale subirurilor sale cu subirul urmat de numrul su de apariii.
Exemplu
Textul T="aaacaaacbbdefdef" poate fi codificat: "a3c1a3c1b2def2"
dar i "aaac2b2def2". Evident, cel de al doilea mod de codificare este mai scurt, deci mai convenabil.
Scriei un program care s codifice optimal un text dat (codul rezultat s fie de lungime minim).
Soluie 1. Spaiul subproblemelor problemei iniiale este format din determinarea unei
codificri optimale pentru caracterele din text de la i pn la j (T[i..j]),
0ij
18 METODA PROGRAMRII DINAMICE
Deoarece jumtatea de sub diagonala principal din matricea l este neutilizat, pentru a putea reconstitui soluia optim, o vom utiliza astfel:
l[j][i]=0, dac l[i][j]=j-i+2 l[j][i]=k, unde k este poziia de splitare a textului pentru
l[i][j]=minI
l[j][i]=-k, unde k este lungimea subirului s care se repet, pentru T[i][j]=minII.
4. Rezolvarea relaiei de recuren: for (int i=0; i
Programare dinamic 19 1 1
char s[DimMax];
if (!k) // cazul I
{strncpy(s,T+i,j-i+1); s[j-i+1]=NULL;
cout
20 METODA PROGRAMRII DINAMICE
Conform acestui tabel, azaleele, de exemplu, vor arta grozav n vaza 2 i
groaznic n vaza 4.
Pentru a obine cel mai plcut efect, trebuie s maximizai suma valorilor estetice ale vazelor, pstrnd ordinea buchetelor. Dac exist mai multe soluii, se cere numai una. (IOI Turcia 1999)
Restricii
1F100 unde F este numrul de buchete de flori. FV100 unde V este numrul de vaze.
-50Aij50 unde Aij este valoarea estetic care se obine punnd buchetul i n vaza j.
Timp maxim de execuie 2 secunde / test.
Date de intrare
Fiierul de intrare se numete flower.in. Prima linie conine dou numere: F
V. Fiecare din urmtoarele F linii conine cte V numere ntregi, astfel nct Aij
este al j-lea numr de pe linia (i+1) din fiierul de intrare.
Date de ieire
Fiierul de ieire flower.out conine dou linii. Prima linie conine suma valorilor estetice a aranjamentului floral. A doua linie reprezint aranjamentul
floral, ca o list de F numere, astfel nct cel de al k-lea numr de pe linie
identific vaza n care este pus buchetul k.
Exemplu flower.in flower.out
3 5
7 23 5 24 16
5 21 -4 10 23
-21 5 -4 -20 20
53
2 4 5
Soluie 1. Subproblemele problemei date constau n amplasarea optim (cu maximizarea
sumei valorilor estetice) a buchetelor 1..i n vazele 1..j, respectnd ordinea
buchetelor (i{1,2,...,F}, j{i,...,V-F+i}).
2. Pentru a reine soluiile subproblemelor vom utiliza o matrice c cu F linii i V
coloane (c[i][j]=valoarea estetic optim care se poate obine amplasnd
buchetele 1..i n vazele 1..j, respectnd ordinea buchetelor. Evident,
valoarea estetic optim se obine n c[F][V]. Pentru reconstituirea soluiei
optime, vom utiliza o matrice poz cu F linii i V coloane (poz[i][j]= vaza
n care plasm buchetul i, ntr-o amplasare estetic optim a buchetelor 1..i
n vazele 1..j).
Programare dinamic 21 1 1
3. Pentru a amplasa optim buchetele 1..i n vazele 1..j, respectnd ordinea
buchetelor (i{1,2,...,F}, j{i,...,V-F+i}) avem dou posibiliti
(dintre care o alegem pe cea mai convenabil): fie amplasm buchetul i n vaza
j i amplasm optimal buchetele 1..i-1 n vazele 1..j-1, fie amplasm
buchetele 1..i n vazele 1..j-1. Prin urmare, caracterizm substructura optimal a problemei prin urmtoarea relaie de recuren:
c[i][i-1]=-;, i{1,2,...,F}
c[0][j]=0; j{0,...,V}
c[i][j]=max{A[i][j]+c[i-1][j-1], c[i][j-1]}, i{1,2,...,F},
j{i,...,V-F+i}
4. Pentru implementare observm putem iniializa c[i][j] cu valoarea Aij,
astfel nct s nu mai fie necesar s utilizm o matrice suplimentar A. Rezolvm relaia de recuren n mod bottom-up astfel:
int i, j;
for (i=1; i
22 METODA PROGRAMRII DINAMICE
clientul, s coboare i s aduc n butoiul din magazin exact cantitatea solicitat de clientul respectiv (cel ce nu a fost servit) .
Clienii sunt restaurante de lux i nu cumpra mai mult de 1 hectolitru.
Cunoscnd cele n cantiti cerute de clieni, s se determine un mod de a rspunde solicitrilor astfel nct, n final, cantitatea de vin vnduta s fie maxim.
Date de intrare
Din fiierul de intrare CERERI.IN se citesc:
n numrul de clieni (n600);
c1 c2 ... cn cantitile (n litri) cerute de clieni, n ordinea sosirii lor.
Date de ieire
n fiierul VANZARI.OUT se va scrie cantitatea vndut (tot n litri).
Exemplu CERERI.IN VANZARI.OUT
4
5 3 4 2
6
Interpretare
Aciunile lui Septic sunt: refuz primul client i pune 5 litri n butoi, l refuz pe al doilea i mai pune nc 3 litri n butoi, iar pe urmtorii doi clieni i servete , realiznd o vnzare de 6 litri. (ONI Timioara 1997, X)
Soluie Subproblemele problemei date constau n determinarea cantitii maxime de vin
ce poate fi vndut lund n considerare cererile clienilor i..n, n ipoteza c
iniial avem n butoi o cantitate j. Soluiile acestor subprobleme le vom reine ntr-
o matrice v.
Relaia de recuren o obinem astfel:
v[i][0]=0, i{1,2,...,n}
v[i][j]= max{v[i+1][j+c[i]] (cazul n care clientul i este refuzat)
c[i]+v[i+1][j-c[i]], dac jc[i]
(cazul n care clientul i este servit)}
Soluia problemei iniiale o vom obine n v[1][0].
O problem de implementare o constituie dimensiunile matricei v: i variaz de
la 1 la n, deci numrul de linii este maxim 600). Numrul de coloane este determinat de cantitatea maxim care se poate acumula n butoi (n cazul cel mai
defavorabil cei 600 de clieni comand fiecare cte 100 de litri), deci numrul
maxim de coloane ar fi 60000. Nu putem aloca n memorie o matrice de
600x60000, dar observm c pentru determinarea liniei i din matricea v este
Programare dinamic 23 1 1
necesar numai linia i+1. Prin urmare este suficient s utilizm doi vectori de
60000 de componente v1 pentru a reine linia precedent (linia i+1) i v2
pentru a calcula linia curent (linia i). Aceti doi vectori vor fi alocai dinamic,
numrul de elemente alocate fiind max (suma tuturor cantitilor cerute de clieni):
unsigned *v1,*v2;
v1=new unsigned[max];
v2=new unsigned[max];
if(!v1 || !v2)
{ cout