Dinamikus programozás Szlávi Péter: Dinamikus programozás 2017.04.06. Dinamikus programozás Szlávi Péter ELTE IK szlavi@ludens.elte.hu 2006. március
Dinamikus programozás * tartalom Szlávi Péter: Dinamikus programozás 2017.04.06. Dinamikus programozás * tartalom 0 Bevezetés 1 Egy gondolatébresztő példa 2 Első példázat * pénzváltás 3 Második példázat * optimális pénzváltás 4 Harmadik példázat * tükörszavak 5 Irodalom 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 0 Bevezetés A lényeg: Valamilyen probléma (optimális) megoldása úgy, hogy rekurzívan visszavezetjük rész-problémák megoldására, de a rekurzió elkerülését (minimális-ra szorítását) egy táblázat felépíté-sével, és újrahasznosításával érjük el… 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa 1.1 Az „iskolapélda” – pénzfelválthatóság Bemenete: P={p1,...,pN} pozitív egészek – a pénzcímletek, és E pozitív egész – a felváltandó összeg Kimenete: FelválthatóE logikai érték – jelentése = fel- váltható-e az E a P halmazban felsorolt cím- letekkel úgy, hogy minden címletet legfeljebb egyszer használunk fel 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa 1.2 A példa „ízlelgetése” A felváltás „szerkezetének” elemzése Egy logikus rekurzív kapcsolat: Tfh. felváltható az E, ekkor (1a) E = pi1+…+pik , feltehető: (1b) i1<…<ik is. Ez esetben világos, hogy E–pik = pi1+…+pik-1 leírása az E–pik és {p1,…,pik-1} paraméterek- kel jellemzett redukált feladatnak 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Részproblémákra bontás A felhasználható címleteket rögzített sorrendűnek tekintve a {p1,…,pi} hal-mazt egyértelműen azonosíthatjuk i-vel. Így bármely (rész)probléma azonosítható az (X,i) paraméter-kettőssel, ahol X a felváltandó összeg és i a felváltáshoz felhasználható címletek utol- sójának indexe Csak ik-1–et írhatunk, hiszen a feldolgozás közben fogalmunk sincs arról, hogy ik-1 gyanánt melyik elem választható. A feladat: (E,N). A (2)-ben megfogal-mazott részfeladat: (E-pik,ik-1). 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Rekurzív összefüggések a részproblé-mák és megoldásaik között (vázlatosan) FV: N N L FV(X,i) = Igaz, ha pi=X, vagy pi<X és FV(X-pi,i-1), vagy FV(X,i-1) i. az éppen szükséges címlet i. felhasználható és a mara-dék felváltható az előzőekkel i. nélkül, az előzőekkel felváltható 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Rekurzív megoldás egy lehetséges algoritmusa type TCimletek=record db:integer; cimlet: array [1..MaxCimletDb] of integer end; var Cimletek:TCimletek; function FV(const X{felváltandó}, i{max.index}:integer):boolean; begin FV:=((i>0) and (Cimletek.cimlet[i]=X)) //i. éppen a kellő címlet or ((i>1) and FV(X,i-1)); //nem az, de i-1.-ig felváltható or ((i>1) and (Cimletek.cimlet[i]<X) and //i. felhasználható FV(X-Cimletek.cimlet[i],i-1)) //és a maradék i-1.-ig felváltható end;//FV ï î í ì Ù > Ú < = 1) - i FV(X, 1 , p FV(X X : i) 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Próbák – elemzések: Kis címletszám (pl. {1,2,5}) mellett „igenlő” a megoldás (pl. 8) – hívási sorrend „tagadó” a megoldás (pl. 9) – hívási sorrend mindkét végeredményhez olyan ada-tok alapján, amelyben van ismétlődő címlet – hívási sorrend, hívás-szám Különféle címletszám (pl. 5, 9, 15, …) mellett olyan összeg, amely azért nem váltható fel, mert túl nagy – hívás-szám növekedése Próbáljuk ki és következtessünk! Zip, exe A „próbáljuk ki” alatti link az előadás alatt, hálózat nélkül elérhető exe-re mutat. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa a) tesztek A stringGridben a 0 értékhez tartozó oszlop (az 1 indexű) a 0 elemszámú címlet megengedése miatt van, hasonlóan a 0 értékhez tartozó sor (a 3 indexű) a 0 érték megengedése miatt van. (Később kiderül, h. teljesen feleslegesen.) … FV:=((i>0) and (Cimletek.cimlet[i]=X)) //i. éppen a kellő címlet or ((i>1) and FV(X,i-1)); //nem az, de i-1.-ig felváltható or ((i>1) and (Cimletek.cimlet[i]<X) and //i. felhasználható FV(X-Cimletek.cimlet[i],i-1)) //és a maradék i-1.-ig felváltható 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa tesztek (folytatás) … FV:=((i>0) and (Cimletek.cimlet[i]=X)) //i. éppen a kellő címlet or ((i>1) and FV(X,i-1)); //nem az, de i-1.-ig felváltható or ((i>1) and (Cimletek.cimlet[i]<X) and //i. felhasználható FV(X-Cimletek.cimlet[i],i-1)) //és a maradék i-1.-ig felváltható 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Tapasztalatok: A hívások módszeresen következnek egy-másután. Akár iterációval is „utánozhat-nánk”. (Legalábbis az ismétlésmentes esetben.) Az ismétlésmentes esetekben a hívás-szá-mok legfeljebb 1 értékűek, azaz legfeljebb egyszeres számolást jeleznek, ami a haté-konyság szempontjából megnyugtató. A 3. futásnál is még legfeljebb 2 az ismétlődő számítás, de a 4.-nél, ami alig különbözik a 3.-tól, már 4 helyen is „tripletet” látunk. S ez rosszat sejtet. kód 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa A hívások során egy bináris fát „járunk be”. Pl. a „9 összeg {1,2,5} címletekkel” futáshoz tartozó bináris fa. … FV:=((i>0) and (Cimletek.cimlet[i]=X)) //i. éppen a kellő címlet or ((i>1) and FV(X,i-1)); //nem az, de i-1.-ig felváltható or ((i>1) and (Cimletek.cimlet[i]<X) and //i. felhasználható FV(X-Cimletek.cimlet[i],i-1)) //és a maradék i-1.-ig felváltható kód 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa tesztek 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Újabb tapasztalatok: Durván növekszik a hívás-szám (mindkét) paraméter növekedtével. A legrosszabb (negatív végeredményű) esetekben a hívás-számokra „gyanús” értékeket kaptunk. Állítás: Ha RekHDb(X,i) az X összeg felbonthatósá-gához szükségez rekurzív hívások számát jelenti (i. címlettel bezárólag), akkor legked-vezőtlenebb esetben a szükséges rekurzív hívások száma: RekHDb(X,i) = 2i–1 A hívás-szám maximumát igenlő esetben is elérhetjük. Példát erre láss itt! Az érték növelésével a rekurziószám növekedése egy ponton megáll. Hiszen a címletösszegnél nagyobb érték esetén ugyanannyi próbálkozást tesz. Az állítás belátásához fel kell ismerni (az FV definíciója alapján), hogy RekHDb(X,i) = RekHDb(X,i-1) + RekHDb(X-pi,i-1) + 1. Világos: a legkedvezőtlenebb eset az, amelynél az Fv(X-pi,i-1) hívás a legtovább végrehajtható, azaz: X> pi. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Röviden: DP. A dinamikus programozásos megoldás Táblázatba gyűjtjük a részproblé-mákra adott válaszokat. A táblázat sorai az egyes X összegek-hez, oszlopai az egyes pi címletekhez rendeli az FV(X,i) értékeket. Éppúgy, ahogy az előbbi programnál tettünk, csakhogy ott tisztán adminisztratív, működés-megértési céllal. A táblázatkitöltést a kis értékek felöl kezdjük: hiszen az FV(X,i) rekurzió-jában FV(X,i–1) és FV(X–pi,i–1) szere-pel. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa A megoldó kód vázlata: Az sgRekTab jelenti most a táblázatot: Tudatosítsuk a kapcsolatot a stringGrid indexek és az összeg/címlet-sorszám között! function PenzValtas_DinProg:boolean; begin Tablafeltoltes(Felvaltando,Cimletek.db); PenzValtas_DinProg:=sgRekTab.Cells[Cimletek.db+1, Felvaltando+2]='+'; end; 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa procedure Tablafeltoltes (const E{felváltandó}, N{max.index}:integer); var i,x:integer; begin with fmPenzValtas do for x:=1 to E do sgRekTab.Cells[2,x+2]:='-';//első oszlop (=2 indexű) Hamis end;//for x //kivéve az 1. cimletnél: if Cimletek.cimlet[1]<=E then //van még cimlet[1]-dik sor? sgRekTab.Cells[2,Cimletek.cimlet[1]+2]:='+'; end;//if … Az elágazás csak ahhoz kell, h. ne indexeljünk túl (nagyon nagy Cimlet[1] miatt) a táblázaton. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa … FV:=((i>0) and (Cimletek.cimlet[i]=X)) //i. éppen a kellő címlet or ((i>1) and FV(X,i-1)); //nem az, de i-1.-ig felváltható or ((i>1) and (Cimletek.cimlet[i]<X) and //i. felhasználható FV(X-Cimletek.cimlet[i],i-1)) //és a maradék i-1.-ig felváltható Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Rekurzív hívás helyett táblahasználat … for i:=2 to N do//az i. oszlop számítása begin for x:=1 to E do if (Cimletek.cimlet[i]=x) or (sgRekTab.Cells[i,x+2]='+') or ((Cimletek.cimlet[i]<x) and (sgRekTab.Cells[i,x-Cimletek.cimlet[i]+2]='+')) then sgRekTab.Cells[i+1,x+2]:='+‘//igaz else sgRekTab.Cells[i+1,x+2]:='-'//hamis {endIf}; end;//for x end;//for i end;//with end;//Tablafeltoltes kód 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Összehasonlító futás: A próbáljuk ki alatti link az előadás alatt, hálózat nélkül elérhető exe-re mutat. Próbáljuk ki és következtessünk! Zip, exe 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Megjegyzések: A rekurzív megoldás fajlagos ismétlési száma: 1 048 575 / 25 267 41 . A DP 222 220 darab táblaelemet szá-mol ki, de csak egyszer. A fajlagos sebesség növekedés: 1 048 575 / 222 220 4,7 . A „feleslegesen” kiszámolt táblaelem szám: (222 220 – 25 267) = 196 953 7,8 szorosa a szükségesnek. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Egy „okosabb” DP megoldás Ötlet: ötvözni a rekurzív megoldás célratörését, azaz „csak azt kiszámol-ni, amit muszáj” elvét a DP megoldás „mindent csak egyszer kiszámolni” elvével. Tehát a számítás logikája rekurzív marad, de mielőtt egy rekurzív hívást kezdeményeznénk, megnézzük, nem lett-e már kiszámolva. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa már ismert a '+' válasz function FV(const X,i:integer):boolean; begin if (fmPenzValtas.sgRekTab.Cells[i+1,X+2]='+') then FV:=true end else if (fmPenzValtas.sgRekTab.Cells[i+1,X+2]='-') then FV:=false end else begin FV:=((i>0) and (Cimletek.cimlet[i]=X)) or ((i>1) and FV(X,i-1)) or ((i>1) and (Cimletek.cimlet[i]<X) and FV(X-Cimletek.cimlet[i],i-1)) {endif}; end;//FV már ismert a ‘-' válasz még nem ismert a válasz kód 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa Összehasonlító futás: A próbáljuk ki alatti link az előadás alatt, hálózat nélkül elérhető exe-re mutat. Próbáljuk ki és következtessünk! Zip, exe 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
1 Egy gondolatébresztő példa Szlávi Péter: Dinamikus programozás 2017.04.06. 1 Egy gondolatébresztő példa 1.3 A DP módszerének váza A megoldás szerkezetének tanulmányozása – részproblémákra bontás megsejtése Részproblémákra és összetevőkre bontás – részproblémák és paramétereik körvonala-zása: a rekurzió előkészítése Részproblémák megoldásának kifejezése rekurzívan az összetevők megoldásaiból – formalizálás: függvénydefiníció Részproblémák megoldásának kiszámítása – a táblaszámítás algoritmizálása kiszámítási sorrend meghatározása: minden részprob-léma minden összetevője előbb szerepeljen a felsorolás-ban az „alulról-felfelé” haladó számítás A megoldás előállítása a 4. lépésben előállított táblázat segítségével – a megoldás algoritmizálása 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
2 Első példázat – pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.1 A feladat Bemenete: P={p1,...,pN} pozitív egészek – a pénzcímletek, és E pozitív egész – a felváltandó összeg Kimenete: SP – a felváltásban szereplő pénzcímletek; az S halmazban felsorolt címleteket legfeljebb egyszer használhatjuk fel 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.2 A megoldás 2.2.1 A megoldás szerkezetének tanulmányozása Ua. mint korábban… 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.2.2 Részproblémákra és összetevők-re bontás A részproblémák a korábbiakhoz hason-lóan fogalmazhatók meg. Az FV(X,i) jelentése viszont más: a legna-gyobb P-beli elem indexe, amely még előfordul az X felváltásában. Pl.: P={2,4,5} N=3; X=7, akkor S={2,5} FV(7,3)=3, mert p3=5, FV(7-p3,3-1)=FV(7-5,3-1)=1, mert p1=2, FV(2-p1,1-1)=FV(2-2,1-1)=FV(0,0). Az előzőhöz képest eltérés az elvárt eredmény jóval összetettebb volta: a logikai érték helyett itt egy halmaz (egy sorozat). A rekurzív gondolatmenetet és az eredmény összetett voltát úgy békítjük össze egymással, hogy leegyszerűsítjük a számítás lényegi, rekurzív részét. Ezért jelölje most FV(X,i) azt a legnagyobb P-beli elem indexét, amely még előfordul a X felváltásában. Ez ugyan még nem a végeredmény, de ebből kiindulva összeszedhetjük a kérdéses halmazt (sorozatot). 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.2.3 Részproblémák megoldásának kifejezése Vegyük észre, hogy akkor N+1 az ered-mény, ha nincs megoldás, s o, ha már nem kell folytatni. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
2 Első példázat – pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.2.4 Részproblémák megoldásának kiszámítása A FV definíciójából látszik: csökkenő pa-raméterekhez nyúl vissza, így a táblaki-töltő számítás kis értékektől indulhat a nagyobbak felé… 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
2 Első példázat – pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás 2.2.5 A megoldás előállítása A megoldás meghatározása most bonyodalmasabb, mint volt korábban: hiszen most egy indexet kapunk a függvény ér-tékeként (k1=FV(E,N)). A táblá-zatból kiolvasható a követke-zőé (k2=FV(E–pk1,k1–1)), majd az azt követőé éít. Amíg a fel-váltandó összegparaméter 0-ra nem csökken. Rekurzív megoldás esetén persze ez a visszalépdelés is rekurzívan történne. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
2 Első példázat – pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás Az sgRekTab-ban az FV-értékek; a KiCimletek-ben képződik az eredmény begin//PenzValtas_DinProg Tablafeltoltes(Felvaltando,Cimletek.db); KiCimletek.db:=0; if strToInt(sgRekTab.Cells[Cimletek.db+1,Felvaltando+2])<= Cimletek.db then begin kX:=Felvaltando; k:=Cimletek.db; while kX>0 do k:=strToInt(sgRekTab.Cells[k+1,kX+2]); inc(KiCimletek.db); KiCimletek.cimlet[KiCimletek.db]:=Cimletek.cimlet[k]; kX:=kX-Cimletek.cimlet[k]; dec(k); end;//while end;//if end;//PenzValtas_DinProg van megoldás: leg-alább egy címlet kX felváltásához szükséges legnagyobb címlet indexe: k A végső megoldást előállító algoritmusban iteratívan dolgozunk, felhasználva az amúgy is létező táblázatot. A tisztán rekurzív megoldásnál természetesen újra rekurzív hívásokkal kellene dolgoznunk. Az adatokat színekkel különítettük el: zöldek a megoldást összeszedő algoritmus szempontjából készek, inputok, pirosak az előállítandók, outputok. kX: a maradék összeg k. címlet már nem lehet, legfeljebb kisebb indexű 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
2 Első példázat – pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 2 Első példázat – pénzváltás Rekurzív DP Összehasonlító futás: A DP-beli kitöltött táblaelemek száma most: (20+1)*(11111+1)=233352. „okos” DP Próbáljuk ki és következtessünk! Rekurzív: Zip, exe; DP: Zip, exe; „okos” DP: Zip, exe. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.1 A feladat Bemenete: P={p1,...,pN} pozitív egészek – a pénzcímletek, és E pozitív egész – a felváltandó összeg Kimenete: SP – a felváltásban szereplő pénzcímletek; az S halmazban felsorolt címleteket legfeljebb egyszer használhatjuk fel; S a lehető legkisebb elemszámú 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2 A megoldás … és nem lehetne „mohóskodni”… ? A problémánkhoz illeszkedő mohó választás: a még választhatók közül a legnagyobb címlet. Egy ellenpélda: P={5,4,4,1,1,1} és E=8; a mohó megoldás: 8=5+1+1+1, ennél jobb: 8=4+4. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2.1 A megoldás szerkezetének tanulmányozása Ua. mint korábban… 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2.2 Részproblémákra és összetevők-re bontás A részproblémák a korábbiakhoz hason-lóan fogalmazhatók meg. Két lépésben oldjuk meg a feladatot. Az Opt(X,i) jelentése: X felváltásához szükséges (első i közül választható) címletek száma. Az FV(X,i) jelentése: a legnagyobb P-beli elem indexe (i), amely még elő-fordul a X felváltásában. (Építünk az Opt-ra.) 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2.3 Részproblémák megoldásának kifejezése Vegyük észre, hogy akkor N+1 az ered-mény, ha nincs megoldás; 0, ha célhoz értünk. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás FV Egy váratlan probléma: Opt A futás adminisztrálását végző táblapár nincs szinkron-ban. Bajt okoz, hogy a bal-felső tábla (1,2) eleme üres. Pedig az alkalmazás foglalkozott vele, hiszen a bal-alsó tábla (1,2) cellája helyesen 1 értéket tartalmaz. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás A probléma magyarázata: Az FV definíciójának optimumra hivatko-zó rekurzív (3.) ágánál tartunk, „készen kapja” a döntéséhez szükséges informá-ciót. Ezért nem bontogatja le sem az (X–pi,i–1), sem az (X,i–1) részproblémákra; így a megoldás alapjául szolgáló, admi-nisztratív táblázat ezen elemei kitöltet-lenek maradnak; és a címleteket összeszedő részben katasz-trófát okoz. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás A probléma megoldása: Az optimum kiszámításra többlet admi-nisztrációt kell bízni: feljegyzi az FV-hez tartozó táblázatba az általa e pil-lanatban még ismert információt, hogy hányadik címlet szerepel a felbontás-ban. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2.4 Részproblémák megoldásának kiszámítása A táblázatgenerálás sorrendje: A címletek szerint „alulról fölfelé” halad-va, de az érték szerint fordítva. A fordított irány magyarázatául: az optimumot kiszámoló függvényhez tar-tozó táblázatot megspórolhatjuk (nincs szükség rá a végeredmény generálásához); mivel csak az előző címlet oszlopára hivat-kozik, elegendő azt és az éppen számítás alatt állót megtartani, sőt egyetlen oszlop is elegendő (lenne:-), ha a kiszámítás sorrendjét megfordítjuk. Ad „egyetlen oszlop is elegendő”: az Opt táblázatára vonatkozik csak; az „előző” oszlop nem nagyobb indexű értékeire „előre-hivatkozva” [(X-0,i-1),(X-pi,i-1), l. (OptFVDef) 3. ágát] haladunk a kisebb E-értékek felé Ad „(lenne:-)”: de nem tesszük az összevethetőség miatt 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás 3.2.5 A megoldás előállítása A megoldás meghatározása most az előző-vel megegyező módon történik. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás az „okos” DP szokásos jelzője A puding próbája: Az alábbi táblázat összefoglalja a re-kurzív és a memorizálós DP alkal-mazás rekurzív hívásainak számát az {1,2,5,10,20,50,100,200,500,1000,1,2,5,10,20,50,100,200,500,1000} címletek esetén: E FV + Opt FV Opt 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás A nem optimális, rekurzív megoldás Az optimális, rekurzív megoldás Összehasonlító futás: Próbáljuk ki és elemezzük! Rekurzív: Zip, exe; DP: Zip, exe; „okos” DP: Zip, exe. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
3 Második példázat – optimális pénzváltás Szlávi Péter: Dinamikus programozás 2017.04.06. 3 Második példázat – optimális pénzváltás Megjegyzések: Kitöltött táblaelemek száma kicsivel több, mint a nem optimális megoldást kereső esetében. (Mindkét táblát figyelem-be véve valamivel több, mint kétszerese.) FV rekurzív hívások száma minimális. Az FV-hez tartozó táblázat kitöltését döntően az Opt függvény végzi. A rekurzív hívások száma kisebb az optimumra nem törekvőénél. Sokkal kevésbé nő az össz rekurzív hívások száma az előbbinél. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.1 A feladat Bemenete: szó={b1,...,bN} szó – jelek sorozata Kimenete: bj természetes szám – minimálisan ennyi jel beillesztésével tehető a szó palindrommá (tükörszóvá). 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.2 A megoldás 4.2.1 A megoldás szerkezetének tanulmányozása TSz(S): az a szöveg, amely minimális számú jel beillesztésével képződik az S-ből. Ilyen biztosan van: S&S’, ahol S’ az S megfordítása. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak Esetek: Ha S=, akkor TSz(S)==S. Ha S egy jelből áll, akkor maga is tükörszó, azaz TSz(S)=S. Legyen S=x&R&y, ahol x, y az S első és utolsó jele, és R akár üres is lehet. Ha x=y, akkor TSz(S)=x&TSz(R)&y. … 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak … Ha xy, akkor TSz(S) első és utolsó jele vagy x vagy y. Ha TSz(S)=x&U&x, ekkor x-et szúr-tunk be a végére, azaz U=TSz(R&y). Ha TSz(S)=y&U&y, ekkor y-t szúrtunk be az elejére, azaz U=TSz(x&R). Vagyis U gyanánt (ami eggyel rövidebb S-nél) a TSz(R&y) és a TSz(x&R) közül azt kell választani, amely kevesebb beszúrással kapható meg. Ui. tegyük föl indirekt: TSz(S)=z&U&z miközben zx és zy (ilyennek kell lennie, hiszen tükörszó). Ekkor U is tükörszó, továbbá a TSz(S) legalább a két z U-hoz vételével keletkezett. Vagyis U is megoldás lett volna az S-hez. Tehát a z&U&z nem minimális. Ellentmondásra jutottunk. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.2.2 Részproblémákra és összetevők-re bontás Jelölések: MSz(i,j) – a minimális jel-beillesztések száma, és szó(i..j) – a szó szöveg i. és j. jele kö-zötti része szó(i):=szó(i..i) – a szó i. jele. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak Kapcsolatok: Ha ij, akkor nincs mit tenni. Ha i<j és szó(i)=szó(j), akkor jel beillesztések számát az MSz(i+1,j–1) részprobléma határozza meg. szó(i)szó(j), akkor az MSz(i+1,j) és az MSz(i,j–1) közül a kisebb értékűt kell választanunk. A kiinduló probléma e jelölésekkel: MSz(1,Hossz(szó)). 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.2.3 Részproblémák megoldásának kifejezése 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.2.4 Részproblémák megoldásának kiszámítása A táblázat generálás sorrendje: Az (i,j)-vel azonosított részprobléma az (i+1,j–1), az (i+1,j) és az (i,j–1) rész-problémáktól függ. Tehát a kiszámítási sorrend i-értelemben fogyó, j-értelem-ben növekvő lehet. Mivel a rekurzió során csak a közvetlen szomszédra van szükség ezért elegendő egyetlen oszlopot tárolni. Pontosabban egyetlen oszlop és egy elem. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak MSz A kód lényegi része: function TukorSzo(const s:string):integer; var T:array [1..MaxN] of integer; i,j,ment,menti:integer; begin T[1]:=0; for j:=2 to N do T[j]:=0; menti:=0; for i:=j-1 downto 1 do ment:=T[i] if s[i]=s[j] then T[i]:=menti else T[i]:=1+Min(T[i],T[i+1]); menti:=ment; end;//for i end;//for j TukorSzo:=T[1] end;//TukorSzo MSz(1,1)0 MSz(j,j)0 T(i)MSz(i,j) MSz(i,j)MSz(i+1,j-1) MSz(i,j)1+Min(MSz(i,j-1),MSz(i+1,j)) TukorSzoMsz(1,N) 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
4 Harmadik példázat – tükörszavak Szlávi Péter: Dinamikus programozás 2017.04.06. 4 Harmadik példázat – tükörszavak 4.2.5 A megoldás előállítása … nem nagy kaland: a tábla (1,Hossz(szó)) eleme, amelyet az algoritmusbeli T vektor első eleme tartalmaz. 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március
Szlávi Péter: Dinamikus programozás 2017.04.06. 5 Irodalom [HGy] Horváth Gyula: „Tehetséggondozó Program – Dinamikus programozás”, NJSzT, 2005 [RISz] Rónyai L.,Ivanyos G.,Szabó R.: Algoritmusok, TYPOTEX, 1999 [SzP] Szlávi Péter: „Dinamikus programozás”, kézirat http://people.inf.elte.hu/szlavi/DP/ DinamikusProgramozas.pdf [SzP2] Szlávi Péter et al.: „További példák a dinamikus programozáshoz”, kézirat http://people.inf.elte.hu/szlavi/ PrM4felev/DinaProg/ 2017.04.06. Szlávi Péter: Dinamikus programozás 2006. március