23
Programare dinamică 1 Metoda programării 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 adoptării unor decizii. Nu există un criteriu pe baza căruia să identificăm cu siguranţă o problemă pentru rezolvarea căreia trebuie să utilizăm metoda programării dinamice, dar putem formula două proprietăţi care sugerează o soluţie prin programare dinamică. Substructură optimală Problema dată poate fi descompusă în subprobleme şi soluţia optimă a problemei depinde de soluţiile optime ale subproblemelor sale. Acest criteriu nu indică neapărat o soluţie 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 execuţie (datorită faptului că problemele se suprapun se ajunge la rezolvarea repetată a aceleiaşi subprobleme). Prin urmare, vom rezolva subproblemele o singură, dată, reţinând rezultatele într-o structură de date suplimentară (de obicei un tablou). Rezolvarea unei probleme prin programare dinamică presupune următorii paşi: 1. Se identifică subproblemele problemei date. 2. Se alege o structură de date suplimentară, capabilă să reţină soluţiile subproblemelor. 3. Se caracterizează substructura optimală a problemei printr -o relaţie de recurenţă. 4. Pentru a determina soluţia optimă, se rezolvă relaţia de recurenţă în mod bottom-up (se rezolvă subproblemele în ordinea crescătoare a dimensiunii lor). În cele ce urmează vom exemplifica pas cu pas modul de rezolvare a problemelor prin metoda programării dinamice.

programare dinamica

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