A lényeget a következő dokumentum 1. fejezete tartalmazza.
A dinamikus programozás (DP) rövid lényegét emígyen határozzák meg Rónyai és társai a [Rónyai L.,Ivanyos G.,Szabó R.: „Algoritmusok”, TYPOTEX, 1999] irodalomban: „A dinamikus programozás módszerek gyakran használatos valamilyen numerikus paramétertől függő érték optimumának meghatározására. Lényege, hogy az optimumot (optimális megoldást) alkalmas kisebb részfeladatok optimumából (optimális megoldásából) próbáljuk előállítani. A dinamikus programozást használó algoritmusok vezérlési szerkezete gyakran emlékeztet egy táblázat szisztematikus (pl. sorról sorra haladó) kiszámítására. A táblázat kitöltését általában egy rekurzív összefüggés teszi lehetővé, ami alapján a bejárási sorrend szerint korábbi elemekből meghatározhatók a többiek. A kapott módszer költségét többnyire a kitöltendő táblázat mérete határozza meg. …”
Mit kell tehát tennünk egy feladat dinamikus megoldásának tervezésekor?
Adott N tárgy (értékük Fi, súlyuk Si). Egy hátizsákba maximum H súlyú tárgyat pakolhatunk. Mennyi a maximális elszállítható érték? (L. az előadásanyag 19-20. diáin!)
Tegyük fel, hogy H≥Si1+Si2+…+Sim (i1<i2<…<im) optimális megoldás, azaz Fi1+Fi2+…+Fim maximális! Ekkor H-Sim≥Si1+Si2+…+Sim-1 (i1<i2<…<im) is optimális, azaz az adott részproblémának megoldása a megoldás megfelelő részlete.
A feladatot jól jellemezhetjük két paraméterrel: az X kapacitással (a zsákba még beleférő súllyal), és a legnagyobb i indexszel, amely a tárgyhalmaz még felhasználható elemeinek részhalmazát meghatározza: (X,i).
Részproblémákra úgy kell bontsuk, hogy az „összetevő” részproblémák paraméterei közül legalább egy változzék. Ha a változás mindig csökkenést (vagy valami maximumfelé haladást) jelent, akkor a körmentessége garantált. Jelen esetben a maximális H súlytól indulva, azt csökkentve, illetve a tárgyak N számának csökkentésével származtatjuk a részproblémákat.
Jelöljük E(X,i)-vel a legnagyobb elszállítható értéket, amely az első i tárgyból egy X kapacítású zsákba bepakolható! Ekkor az E(X,i) így definiálandó:
E:Súly×Index→Érték, Súly,Index,Érték=N E(X,i):=F1 , ha i=1 ∧ S1≤X (1) E(X,i):=0 , ha i=1 ∧ S1>X (2) E(X,i):=E(X,i-1) , ha i>1 ∧ Si>X (3) E(X,i):=max(E(X,i-1),Fi+E(X-Si,i-1) , egyébként (4)
A feladat megoldását az E(H,N) jelenti.
Ez legyen házi feladat, gyakorlásként, és hogy lássuk mennyi rekurzív hívást kíván! Ha kíváncsi az én megoldásomra: töltse le! … és két bemeneti fájl: 4.be, 20.be hozzá.
A rekurziót kell feloldani: egy táblázat megfelelő sorrendű kiszámításával. A táblázatról:
A továbbiakban az E-vel már a mátrixot jelöljük (hiszen az E függvény alapján áttértünk rá).
[Programparaméterek – ábrázolás --------------------------------------------------------] Konstans MaxN:Egész(???) [a tárgyak maximális száma] MaxH:Egész(???) [a zsák kapacitásának maximális értéke] Típus [a feladatbeli S és F tömbök „egyesített” megfelelőjénet típusa:] TTárgy=Rekord(súly,érték:Egész) TTárgyak=Tömb(1..MaxN:TTárgy) TTab=Tömb(0..MaxH,1..MaxN:Egész) [a dinamikus programozás táblázata] Változó Tárgyak:TTárgyak [a feladatbeli S, F tömbök megfelelője; globálisan elérhető] … [A lényegi függvény – implementálás ----------------------------------------------------] Függvény MaxÉrték(Konstans h,n:Egész):Egész Változó i,x:Egész E:TTab [Az 1. oszlop kiszámolása --------------------------------------------] E(0..Tárgyak(1).súly-1,1):=0 [⇐(2)] E(Tárgyak(1).súly..h,1):=Tárgyak(1).érték [⇐(1)] [Az i=2..n. oszlop kiszámolása ---------------------------------------] Ciklus i=2-től n-ig Ciklus x=0-tól h-ig E(x,i):=E(x,i-1) [⇐(3)] Ha Tárgyak(i).súly≤x és E(x,i)<Tárgyak(i).érték+E(x-Tárgyak(i).súly,i-1) akkor E(x,i):=Tárgyak(i).érték+E(x-Tárgyak(i).súly,i-1) [⇐(4)] Elágazás vége Ciklus vége Ciklus vége [♥] MaxÉrték:=E[h,n] Eljárás vége.
Figyelje meg az alábbi példamátrixot!
A megoldás, azaz a programparaméterek és a főprogram:
… Változó [Bemenet:] N,H:Egész Tárgyak:TTárgyak [a definícióbeli S, F tömbök megfelelője; globálisan elérhető] [Kimenet:] Érték:Egész … [adat-beolvasás] Érték:=MaxÉrték(H,N) … [eredmény-kiírás]
Ha kíváncsi az én megoldásomra: töltse le! … és két bemeneti fájl: 4.be, 20.be hozzá.
Kérdés: mi van akkor, ha a súly (és az érték) nem egész, hanem valós szám?
Adott N tárgy (értékük Fi, súlyuk Si). Egy hátizsákba maximum H súlyú tárgyat pakolhatunk. Mennyi a maximális elszállítható érték, mely tárgyakat pakoljuk a zsákba? (L. az előadásanyag 19-22. diáin!)
L. előző megoldásnál!
Ennél a megoldásnál követjük az előbbi, alapfeladat megoldásánál alkalmazott gondolatmenetet. Erre fogunk építkezni. L. előző megoldásnál!
A feladat megoldását részben (ti. a maximális értéket) az E(H,N) mátrix tartalmazza. L. előző megoldásnál!
Emellett azonban össze kell szedni a megoldásban szereplő tárgyakat is. Ez elvégezhető az E mátrix segítségével: az E(H,N)-ből kiindulva visszafelé lépdelve, és követve a választott tárgy súlyát, a még rendelkezésre álló kapacítást, és az össz értéket.
[Programparaméterek – ábrázolás --------------------------------------------------------] Konstans MaxN:Egész(???) [a tárgyak maximális száma] MaxH:Egész(???) [a zsák kapacitásának maximális értéke] Típus TTárgy=Rekord(súly,érték:Egész) TTárgyak=Tömb(1..MaxN:TTárgy) TTab=Tömb(1..MaxH,1..MaxN:Egész) [a dinamikus programozás táblázata] TSorszámok=Tömb(1..MaxN:Egész) [A lényegi függvény – implementálás ----------------------------------------------------] Eljárás Hátizsák(Konstans h,n:Egész, Változó db:Egész, zstk:TSorszámok, érték:Egész): Változó i,x:Egész E:TTab [Az 1. oszlop kiszámolása --------------------------------------------] E(0..Tárgyak(1).súly-1,1):=0; E(Tárgyak(1).súly..h,1):=Tárgyak(1).érték [Az i=2..n. oszlop kiszámolása ---------------------------------------] Ciklus i=2-től n-ig Ciklus x=0-tól h-ig E(X,i):=E(x,i-1) Ha Tárgyak(i).súly≤x és E(x,i)<Tárgyak(i).érték+E(x-Tárgyak(i).súly,i-1) akkor E(x,i):=Tárgyak(i).érték+E(x-Tárgyak(i).súly,i-1) Elágazás vége Ciklus vége Ciklus vége Összegyűjt(h,n,E,db,zstk,érték) Eljárás vége.
… és a plusz eredményparamétereket összeszedő eljárás:
Eljárás Összegűjt(Konstans h,n:Egész, E:TTab, Változó db:Egész, zstk:TSorszámok, érték:Egész): Változó x,i:Egész i:=n; x:=h; db:=0; érték:=0 Ciklus i>0 [≡van még tárgy] és E(x,i)>0 [≡van még hely] Ciklus amíg i>1 és E(x,i)=E(x,i-1) [≡az i. nincs felhasználva] i:-1 Ciklus vége db:+1; zstk(db):=i [az i. a következő felhasznált] x:=x-Tárgyak(i).súly [már csak x súly fér a zsákba] érték:+Tárgyak(i).érték [az eddigi összérték] i:-1 Ciklus vége Eljárás vége.
Egy szóba minimálisan hány karaktert kell beszúrni, hogy tükörszó legyen belőle (azaz ugyanaz legyen balról jobbra és jobbról balra olvasva is)! Egy szót tükörszónak nevezünk, ha balról és jobbról kiolvasva betűről betűre megegyezik. (Tehát minden egybetűs szó tükörszó.) Minden szó felbontható részekre úgy, hogy minden rész tükörszó legyen. Minimálisnak nevezzük az olyan felbontást, amely egy szót a lehető legkevesebb tükörszóra szed szét. Írjon programot a minimális tükörszó partíciók számának meghatározására.
Példa:
Ha kíváncsi az én megoldásomra: töltse le!