Dinaminis programavimas: Skirtumas tarp puslapio versijų

Straipsnis iš Vikipedijos, laisvosios enciklopedijos.
Ištrintas turinys Pridėtas turinys
VP-bot (aptarimas | indėlis)
S wiki sintakse 2
VP-bot (aptarimas | indėlis)
S wiki sintakse 3
Eilutė 37: Eilutė 37:
Šio tipo uždaviniai gana dažni. Bendrai jie formuluojami taip: turime <math>N</math> daiktų, bei žinome jų dydžius <math>D_i</math> bei vertes <math>V_i</math>. Kuprinės dydis yra <math>K</math>, taigi galima paimti tik tiek daiktų, kad jų dydis neviršytų <math>K</math>. Reikia surasti tokį daiktų rinkinį, kurio vertė būtų didžiausia.
Šio tipo uždaviniai gana dažni. Bendrai jie formuluojami taip: turime <math>N</math> daiktų, bei žinome jų dydžius <math>D_i</math> bei vertes <math>V_i</math>. Kuprinės dydis yra <math>K</math>, taigi galima paimti tik tiek daiktų, kad jų dydis neviršytų <math>K</math>. Reikia surasti tokį daiktų rinkinį, kurio vertė būtų didžiausia.


Dinaminio sprendimo idėja:
Dinaminio sprendimo idėja:
*Tarkime, nagrinėjame <math>J</math>-tąjį daiktą, o kuprinėje dar yra <math>K</math> talpos vienetų
* Tarkime, nagrinėjame <math>J</math>-tąjį daiktą, o kuprinėje dar yra <math>K</math> talpos vienetų
:*Jeigu daiktą imame, tuomet galime iš <math>J-1</math> daiktų paimti tiek, kad neviršytų <math>K-D_j</math>
:* Jeigu daiktą imame, tuomet galime iš <math>J-1</math> daiktų paimti tiek, kad neviršytų <math>K-D_j</math>
:*Jeigu neimame, tuomet galime iš <math>J-1</math> daiktų paimti tiek, kad neviršytų <math>K</math>
:* Jeigu neimame, tuomet galime iš <math>J-1</math> daiktų paimti tiek, kad neviršytų <math>K</math>
*Iš šių dviejų atvejų, pasirenkme vertingesnį.
* Iš šių dviejų atvejų, pasirenkme vertingesnį.


Taigi, problemą <math>J</math> daiktų atveju galime išspresti, jeigu žinome problemos <math>J-1</math> daiktų daiktų atveju sprendimą. Matematiškai tai atrodo taip: <math>F(j, \mbox{ } k) = max(F(j-1,\mbox{ } k), \mbox{ } F(j-1, \mbox{ } k-D_j) + V(j))</math>. Sprendimą galima rasti, ieškant nuo apačios, t.y. pirma apskaičiuojant <math>F</math> reikšmes su mažesnėmis <math>J</math> reikšmėmis. Taip pat, būtina atkreipti dėmesį, kad būtina turėti tam tikras „ribines“ reikšmes. Šiuo atveju tai būtų: <math>F(0, \mbox{ } k) = 0</math>.
Taigi, problemą <math>J</math> daiktų atveju galime išspresti, jeigu žinome problemos <math>J-1</math> daiktų daiktų atveju sprendimą. Matematiškai tai atrodo taip: <math>F(j, \mbox{ } k) = max(F(j-1,\mbox{ } k), \mbox{ } F(j-1, \mbox{ } k-D_j) + V(j))</math>. Sprendimą galima rasti, ieškant nuo apačios, t.y. pirma apskaičiuojant <math>F</math> reikšmes su mažesnėmis <math>J</math> reikšmėmis. Taip pat, būtina atkreipti dėmesį, kad būtina turėti tam tikras „ribines“ reikšmes. Šiuo atveju tai būtų: <math>F(0, \mbox{ } k) = 0</math>.

05:52, 14 liepos 2009 versija

Dinaminis programavimasprogramavimo metodas, paremtas uždavinio skaidymu į mažesnes susijusias problemas, bei tų problemų sprendimų įsiminimu. Taigi laiko sanaudos pakeičiamos atminties sanaudomis. Jis naudojamas, kuomet „Skaldyk ir valdyk“ nėra pakankamai efektyvus. Gali būti pritaikomas įvairaus tipo uždaviniams, tačiau šio metodo taikymo galimybę pastebėti ne visuomet lengva.

Fibonačio skaičiai

Apibrėžimas: , , . Reikia apskaičiuoti -tąjį sekos narį. Rekursyvus sprendimas būtų toks:

 int Fibonacci(int n) {
   if (n < 2) {
     return 1;
   } else {
     return Fibonacci(n-1) + Fibonacci(n-2);
   }
 }

Dinamiškai galime parašyti taip:

 int Fibonacci[N];
 
 Fibonacci[0] = Fibonacci[1] = 1;
 for (int i = 2; i < N; i++) {
   Fibonacci[i] = Fibonacci[i-1] + Fibonacci[i-2];
 }

Taip gauname visas reišmes nuo iki .

Taip pat yra algoritmas surasti tam tikrą Fibonačio skaičių:

 Fibonacci[0] := 1;
 Fibonacci[1] := 1;
 for i := 2 to n do
   begin
     tmp := Fibonacci[0];
     Fibonacci[0] := Fibonacci[1];
     Fibonacci[1] := Fibonacci[0] + tmp;
   end;

"Kuprinės" uždavinys

Šio tipo uždaviniai gana dažni. Bendrai jie formuluojami taip: turime daiktų, bei žinome jų dydžius bei vertes . Kuprinės dydis yra , taigi galima paimti tik tiek daiktų, kad jų dydis neviršytų . Reikia surasti tokį daiktų rinkinį, kurio vertė būtų didžiausia.

Dinaminio sprendimo idėja:

  • Tarkime, nagrinėjame -tąjį daiktą, o kuprinėje dar yra talpos vienetų
  • Jeigu daiktą imame, tuomet galime iš daiktų paimti tiek, kad neviršytų
  • Jeigu neimame, tuomet galime iš daiktų paimti tiek, kad neviršytų
  • Iš šių dviejų atvejų, pasirenkme vertingesnį.

Taigi, problemą daiktų atveju galime išspresti, jeigu žinome problemos daiktų daiktų atveju sprendimą. Matematiškai tai atrodo taip: . Sprendimą galima rasti, ieškant nuo apačios, t.y. pirma apskaičiuojant reikšmes su mažesnėmis reikšmėmis. Taip pat, būtina atkreipti dėmesį, kad būtina turėti tam tikras „ribines“ reikšmes. Šiuo atveju tai būtų: .

Programos fragmentai:

 for J := 1 to N do
   begin
     F[J, K] := F[J-1, K];
     if D[J] <= K then
       V[J, K] := Max(V[J, K], V[J-1, K-D[J]] + V[J]);
   end;