dynamic programming recursieve datastructuren college 11 Fibonacci met tabel



Vergelijkbare documenten
Programmeermethoden. Recursie. week 11: november kosterswa/pm/

Datastructuren college 10

Programmeermethoden. Recursie. Walter Kosters. week 11: november kosterswa/pm/

REEKS II. Zaterdag 6 november 2010, 11u

Datastructuren: stapels, rijen en binaire bomen

Achtste college algoritmiek. 8 april Dynamisch Programmeren

Tweede college algoritmiek. 12 februari Grafen en bomen

Uitwerking tentamen Algoritmiek 10 juni :00 13:00

2 Recurrente betrekkingen

REEKS I. Zaterdag 6 november 2010, 9u

Uitwerking tentamen Algoritmiek 9 juli :00 13:00

Programmeermethoden. Pointers. Walter Kosters. week 10: november kosterswa/pm/


Algoritmiek. 15 februari Grafen en bomen

Recursion. Introductie 37. Leerkern 37. Terugkoppeling 40. Uitwerking van de opgaven 40

extra oefening algoritmiek - antwoorden

Verslag Opdracht 4: Magische Vierkanten

Tentamen Object Georiënteerd Programmeren TI januari 2013, Afdeling SCT, Faculteit EWI, TU Delft

recursie Hoofdstuk 5 Studeeraanwijzingen De studielast van deze leereenheid bedraagt circa 6 uur. Terminologie

Recursie: definitie. De som van de kwadraten van de getallen tussen m en n kan als volgt gedefinieerd worden:

Examen Programmeren 2e Bachelor Elektrotechniek en Computerwetenschappen Faculteit Ingenieurswetenschappen Academiejaar juni, 2010

ALGORITMIEK: antwoorden werkcollege 5

Online c++ leren programmeren:

definities recursieve datastructuren college 13 plaatjes soorten Graph = ( V, E ) V vertices, nodes, objecten, knopen, punten

Een eenvoudig algoritme om permutaties te genereren

Uitwerking tentamen Algoritmiek 9 juni :00 17:00

9. Strategieën en oplossingsmethoden

Tentamen Imperatief en Object-georiënteerd programmeren in Java voor CKI

Inleiding Programmeren 2

Modelleren en Programmeren

Small Basic Programmeren Text Console 2

Modelleren en Programmeren

Vierde college algoritmiek. 2 maart Toestand-actie-ruimte Exhaustive Search

Twaalfde college complexiteit. 11 mei Overzicht, MST

Als een PSD selecties bevat, deelt de lijn van het programma zich op met de verschillende antwoorden op het vraagstuk.

software constructie recursieve datastructuren college 15 5 stappen plan ontwerpen de software bestaat uiteindelijk uit datatypen functies

Examen Datastructuren en Algoritmen II

Een typisch programma in C en C++ bestaat uit een aantal onderdelen:

Tentamen Programmeren in C (EE1400)

Modelleren en Programmeren

Informatica: C# WPO 10

OEFENINGEN PYTHON REEKS 6

TEST INFORMATICA 1STE BACHELOR IN DE INGENIEURSWETENSCHAPPEN - ACADEMIEJAAR

Uitgebreide uitwerking tentamen Algoritmiek Dinsdag 5 juni 2007, uur

7 Omzetten van Recursieve naar Iteratieve Algoritmen

Examen Programmeren 2e Bachelor Elektrotechniek en Computerwetenschappen Faculteit Ingenieurswetenschappen Academiejaar juni, 2010

SEQUENTIE-STRUCTUUR. Oefening: Dichtheid

Uitwerking Aanvullend tentamen Imperatief programmeren Woensdag 24 december 2014, uur

Elfde college algoritmiek. 18 mei Algoritme van Dijkstra, Heap, Heapify & Heapsort

Datastructuren Uitwerking jan

Programmeertechnieken

Programmeermethoden. Functies vervolg. Walter Kosters. week 5: 1 5 oktober kosterswa/pm/

Inleiding Programmeren 2

Vijfde college algoritmiek. 2/3 maart Exhaustive search

Overzicht. 1. Definities. 2. Basisalgoritme. 3. Label setting methoden. 4. Label correcting methoden. 5. Ondergrenzen. 6.

10 Meer over functies

Vierde college algoritmiek. 23/24 februari Complexiteit en Brute Force

VOORBLAD SCHRIFTELIJKE TOETSEN

Datastructuren: stapels, rijen en binaire bomen

Combinatoriek groep 1 & 2: Recursie

Discrete Structuren. Piter Dykstra Opleidingsinstituut Informatica en Cognitie

Planning. 1. Mini College. 2. Introductiecursus Imperatief Programmeren. 3. Crash and Compile (vanaf 17:00 uur)

Negende college algoritmiek. 6/7 april Dynamisch Programmeren

Programmeren in C++ Efficiënte zoekfunctie in een boek

De Leidsche Flesch Studievereniging voor Natuurkunde, Sterrenkunde, Wiskunde en Informatica sinds DLF Pointerworkshop

Dynamisch Programmeren. Het Rugzakprobleem

Examen Datastructuren en Algoritmen II

Algoritmen, Datastructuren en Complexiteit ( ) Uitwerkingen

li d a l n s V a l GEMEENTE MAARTENSDIJK r Nbo bestemmingsplan buitengebied g g Nbo Nbo Schaal 1:5000 plankaart noord

Achtste college algoritmiek. 12 april Verdeel en Heers. Dynamisch Programmeren

Vierde college algoritmiek. 1 maart Toestand-actie-ruimte Brute Force

HOGESCHOOL VAN AMSTERDAM Informatica Opleiding. CPP 1 van 10

Tentamen combinatorische optimalisatie Tijd:

Negende college algoritmiek. 15 april Dynamisch Programmeren

Voorbeeldtentamen Inleiding programmeren (IN1608WI), Oktober 2003, , Technische Universiteit Delft, Faculteit EWI, Afdeling 2.

DOMjudge teamhandleiding

Tentamen Programmeren in C (EE1400)

HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Module 4 Programmeren

Opgaven Zoekbomen Datastructuren, 15 juni 2016, Werkgroep.

ALGORITMIEK: answers exercise class 7

Programmeermethoden NA. Week 6: Lijsten

Tentamen in2705 Software Engineering

Modelleren en Programmeren

2.0 Voorkennis. Rekenregels machten: 5) a 0 = 1. p p q p q a p q q. p q pq p p p. Willem-Jan van der Zanden

Programmeren met Arduino-software

D-dag 2014 Vrijeschool Zutphen VO. D -DAG 13 februari 2014: 1+ 1 = 2. (en hoe nu verder?) 1 = 2en hoe nu verder?

Practicum hoogtemeting 3 e klas havo/vwo

Uitgebreide uitwerking Tentamen Complexiteit, juni 2017

Lineaire data structuren. Doorlopen van een lijst

Datastructuren Uitwerking jan

Informatica: C# WPO 13

Programmeermethoden. Arrays (vervolg 2) Walter Kosters. week 9: 5 9 november kosterswa/pm/

Combinatoriek groep 1

Tree traversal. Bomen zijn overal. Ferd van Odenhoven. 15 november 2011

Tentamen Objectgeorienteerd Programmeren IN1205 Voorbeeld

Derde college complexiteit. 7 februari Zoeken

Recursie. public static int faculteit( int n ){ // Deze functie berekent n! // pre: n = N en n >= 0 // post: faculteit = N!

Onafhankelijke verzamelingen en Gewogen Oplossingen, door Donald E. Knuth, The Art of Computer Programming, Volume 4, Combinatorial Algorithms

Transcriptie:

dynamic programming recursieve datastructuren college 11 dynamic programming onthouden of opnieuw berekenen? idee: onthoud tussenresultaten van de berekingen om herhaald uitrekenen te voorkomen hier vooral meervoudig recursieve functies we hebben geschikt datastructuur nodig ruimte-complexiteit is meestal slechter algoritme moet wat aangepast worden we zijn dit al eerder tegen gekomen fibonacci met tabel driehoek van Pascal... 1 2 Fibonacci met tabel Fibonacci over de groei van konijnen + + + + + + int fib ( int n ) return n<2? 1 : fib (n-1) + fib (n-2); 1 1 2 3 5 8 13 21 0 1 2 3 4 5 6 7 fib is O ( 2 n ) preciezer O ( 1.618 n ) fib (n-2) wordt 2 keer uitgerekend fib (n-3) wordt 4 keer uitgerekend etc.. dynamic programming stop resultaten in een tabel zoek waarden op in tabel i.p.v. ze uit te rekenen voor n>1: fib(n) = fib(n-1)+fib(n-2) 3 4 1

Fibonacci met dynamic programming maak een tabel met fib[m] voor m n int fibdp (int n ) int* fibrij = newint [ n+1 ]; fibrij [ 0 ] = fibrij [ 1 ] = 1; for (int i = 2; i<=n; i+=1 ) fibrij [ i ] = fibrij [ i-1 ] + fibrij [ i-2 ]; return fibrij [ n ]; dit is O(n) recurente betrekking 5 Fibonacci tabel in O ( 1 ) ruimte dit kan ook in O ( n ) tijd en in O ( 1 ) ruimte alleen de laatste 2 elementen uit de tabel zijn nodig kan vaak in dynamic programming int fibdp2 (int n ) int laatste = 1, vorige = 1; for ( ; n>1 ; n-=1 ) int nieuwe = laatste + vorige; vorige = laatste; laatste = nieuwe; return laatste; 6 n n! k = k!( n k)! naïeve implementatie driehoek van Pascal 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 ook overflow probleem int bincoef ( int n, int k ) return fac ( n ) / ( fac ( k ) * fac ( n-k )); als we fac steeds uitrekenen, element O ( n ) tabel O (n 3 ) ook dit kan veel beter 7 driehoek van Pascal onthoud de vorige rij hoeken altijd waarde 1 andere elementen som van bovenburen void driehiekpascal ( int m ) int *rij = newint [ m+1 ]; for ( int k=0; k<=m ; k+=1 ) for ( int n=k; n>=0 ; n-=1 ) slechts O(n) geheugen van k naar 0, gebruik symmetrie cout << (rij[n] = n==k n==0? 1 : rij[n]+rij[n-1]) << ' '; cout << endl; handig maar lelijk, vullen en afdrukken in een keer elementen in O ( 1 ), hele driehoek in O ( n 2 ) 8 2

één binomiaal coëfficiënt één binomiaal coëfficiënt met tabel int bincoef ( int n, int k ) return fac ( n ) / ( fac ( k ) * fac ( n-k )); ongeschikt voor dynamic programming maar tabel van fac kan natuurlijk wel recursieve formulering binomiaal coëfficiënten int bincoef ( int n, int k ) if ( n==k n==0 ) return 1; return bincoef ( n, k-1 ) + bincoef ( n-1, k-1 ) ; hier kunnen we direct een tabel voor maken 9 int bincoefdp ( int n, int k ) int* r = newint [k+1]; for (int l=1; l<=k; l+=1 ) for (int m=l; m>=0; m-=1 ) if ( m==l m==0 ) r[m] = 1; r[m] = r[m] + r[m-1] ; return r[n]; 10 spannender probleem edit-distance van strings: aantal edit-acties dat nodig is om ene string in andere om te zetten toegestane edit acties: substitution: vervang één letter door één andere spot shot, man mal, maan baan insertion: voeg één letter toe pot spot, pot poot, ma man deletion: gooi één letter weg spot pot, poot pot, man ma we gaan dit implementeren als een functie int editdistance ( char s [ ], char t [ ] ) 11 acceptatietest class testeditdistance : public Test public: void run ( ) test_ ( editdistance ( "", "" ) == 0 ) ; test_ ( editdistance ( "a", "" ) == 1 ) ; randgevallen test_ ( editdistance ( "", "a" ) == 1 ) ; test_ ( editdistance ( "a", "a" ) == 0 ) ; test_ ( editdistance ( "a", "b" ) == 1 ) ; test_ ( editdistance ( "abcd", "dcba" ) == 4 ) ; 'normale' test_ ( editdistance ( "abcd", "dabc" ) == 2 ) ; gevallen test_ ( editdistance ( "shot", "spot" ) == 1 ) ; test_ ( editdistance ( "ago", "agog" ) == 1 ) ; test_ ( editdistance ( "hour", "our" ) == 1 ) ; test_ ( editdistance ( "programma", "implementatie" )==11 ) ; ; groot geval 12 3

recursief algoritme beschouw een string als bron en de ander als doel in hoeveel acties kunnen we bron omzetten in doel ( omgekeerd is precies even veel stappen ) voor de laatste letter zijn er 4 mogelijkheden: past: geen actie nodig past niet, een van de volgende acties: substitute: vervang bestaande letter door gewenste insert: voeg gewenste letter toe delete: gooi bestaande letter weg ga recursief verder met de rest kosten van edit-acties stop het in een functie om flexibel te zijn voorlopig kosten alle acties 1: int match ( char c, char d ) return c==d? 0 : 1 ; int inschar ( char c ) return 1; int delchar ( char c ) return 1; match substitute we hadden ook vooraan kunnen beginnen 13 insert en delete 14 eerste aanzet begin achteraan geen zin om steeds het woord aan te passen het einde op te zoeken geef index van laatste letter steeds mee int editdistance ( char s [ ], char t [ ] ) return computedistance ( s, t, strlen ( s )-1, strlen ( t )-1 ); 15 computedistance int computedistance ( char s [ ], char t [ ], int i, int j ) klaar? if ( i<0 && j<0 ) return 0; s leeg? if ( i<0 ) return inschar( t [ j ] ) + computedistance ( s, t, i, j-1 ); if ( j<0 ) t leeg? return delchar( s [ i ] ) + computedistance ( s, t, i-1, j ); match: substitute of past return min ( computedistance ( s, t, i-1, j-1 ) + match ( s[i], t[j] ), computedistance ( s, t, i, j-1 ) + inschar ( t [ j ] ), computedistance ( s, t, i-1, j ) + delchar ( s [ i ] ) ); merk op: strings zelf worden niet veranderd 16 4

aanroep geef de index van de laatste letters mee als beginwaarde int edit_distance ( char s [ ], char t [ ] ) return computedistance ( s, t, strlen ( s )-1, strlen ( t )-1 ); 17 computedistance evaluatie de test voor dit programma slaagt, het is ook correct voor wat langere strings (zeg lengte 12), is het erg langzaam! return min ( computedistance ( s, t, i-1, j-1 ) + match ( s[i], t[j] ), computedistance ( s, t, i, j-1 ) + inschar ( t[j] ), computedistance ( s, t, i-1, j ) + delchar ( s[i] ) ); drievoudige recursie! zelfs als we aannemen dat beide indices afnemen is het O ( 3 n )! kan dit beter? maak voor gegeven s en t tabel voor distance[i][j] 18 dynamic programming int edit_distancedp (char s [], char t [] ) int len_s = strlen ( s ), len_t =strlen ( t ); int ** m = newint* [ len_s+1 ]; for (int i=0; i<=len_s ; i+=1 ) m [ i ] = newint [ len_t+1 ]; m [ 0 ] [ 0 ] = 0; // alloceer tabel // kosten voor lege strings for (int i=1; i<=len_s; i+=1 ) // initialiseer randen m [ i ] [ 0 ] = m [ i-1 ] [ 0 ] + inschar ( s [ i-1 ] ); for (int j=1; j<=len_t; j+=1 ) m [ 0 ] [ j ] = m [ 0 ] [ j-1 ] + delchar ( t [ j-1 ] ); for (int i=1; i<=len_s; i+=1 ) // vul tabel for (int j=1; j<=len_t; j+=1 ) m [ i ] [ j ] = min ( m [ i-1 ] [ j-1 ] + match ( s [ i-1 ], t [ j-1] ), m [ i ] [ j-1 ] + inschar( t [ j-1 ] ), m [ i-1 ] [ j ] + delchar( s [ i-1 ] ) ); return m [ len_s ] [ len_t ]; opzoeken in tabel 19 standaard voorbeeld cout << "Distance " << edit_distancedp ( "thou shalt not", "you should not" ) << endl; geeft Distance 5 via welk pad dan? 20 5

de afstandsmatrix 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 1 2 3 4 5 6 7 8 9 10 11 12 13 13 2 2 2 3 4 5 5 6 7 8 9 10 11 12 13 3 3 2 3 4 5 6 5 6 7 8 9 10 11 12 4 4 3 2 3 4 5 6 5 6 7 8 9 10 11 5 5 4 3 2 3 4 5 6 6 7 7 8 9 10 6 6 5 4 3 2 3 4 5 6 7 8 8 9 10 7 7 6 5 4 3 2 3 4 5 6 7 8 9 10 8 8 7 6 5 4 3 3 4 5 6 7 8 9 10 9 9 8 7 6 5 4 4 4 4 5 6 7 8 9 10 10 9 8 7 6 5 5 5 5 5 6 7 8 8 11 11 10 9 8 7 6 6 6 6 6 5 6 7 8 12 12 11 10 9 8 7 7 7 7 7 6 5 6 7 13 13 12 11 10 9 8 7 8 8 8 7 6 5 6 14 14 13 12 11 10 9 8 8 9 9 8 7 6 5 doel 21 hoe kom ik er wat is het pad van thou-shalt-not, naar you-should-not? antwoord: DSMMMMMISMSMMMM D: delete S: substitute I: insert M: match hoe komen we hieraan? edit acties bijhouden in matrix edit acties reconstrueren uit matrix 22 action matrix y o u - s h o u l d - n o t B I I I I I I I I I I I I I I t D M M M M M M M M M M M M M M h D M M M M M M I I I I I I I I o D M M M M M M M I I I I I M I u D M D M I I I I M I I I I I I - D M D D M I I I I M M M I I I s D M D D D M I I I I M M M M M h D M D D D D M I I I I I I M M a D M D D D D D M M M M M M M M l D M D D D D D M M M I I I I I t D M D D D D D M M M M M M M M - D M D D M D D M M M M M I I I n D M D D D D D M M M M D M I I o D M M D D D D M M M M D D M I t D M D D D D D D M M M D D D M afdrukken alternatief als je goed je best doet kun je ook zonder de action tabel begin rechts onder bekijk 3 buren om te beslissen welke stap je hebt gekozen als beste toe je de matrix vulde ga die kant op herhaal dit totdat je in m[0][0] bent. pad:d S M M M M M I S M S M M M M 23 24 6

action matrix y o u - s h o u l d - n o t 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 t 1 1 2 3 4 5 6 7 8 9 10 11 12 13 13 h 2 2 2 3 4 5 5 6 7 8 9 10 11 12 13 o 3 3 2 3 4 5 6 5 6 7 8 9 10 11 12 u 4 4 3 2 3 4 5 6 5 6 7 8 9 10 11-5 5 4 3 2 3 4 5 6 6 7 7 8 9 10 s 6 6 5 4 3 2 3 4 5 6 7 8 8 9 10 h 7 7 6 5 4 3 2 3 4 5 6 7 8 9 10 a 8 8 7 6 5 4 3 3 4 5 6 7 8 9 10 l 9 9 8 7 6 5 4 4 4 4 5 6 7 8 9 t 10 10 9 8 7 6 5 5 5 5 5 6 7 8 8-11 11 10 9 8 7 6 6 6 6 6 5 6 7 8 n 12 12 11 10 9 8 7 7 7 7 7 6 5 6 7 o 13 13 12 11 10 9 8 7 8 8 8 7 6 5 6 t 14 14 13 12 11 10 9 8 8 9 9 8 7 6 5 pad:d S M M M M M I S M S M M M M 25 afdrukken van het pad void printpad (int *m [], char s [], char t [], int i, int j ) if ( i==0 ) if ( j==0 ) return; // klaar! printpad ( m, s, t, i, j-1 ); // eerst de voorgaande cout << " I" << t [ j-1 ]; // insert if ( j==0 ) printpad ( m, s, t, i-1, j ); // eerst de voorgaande cout << " D" << s [ i-1 ]; // delete... zie volgende pagina 26... afdrukken deel 2 int matchcost = m [i-1][j-1] + match( s [ i-1 ], t [ j-1 ] ), insertcost = m [i ][j-1] + inschar( t [ j-1 ] ), deletecost = m [i-1][j ] + delchar( s [ i-1 ] ); if ( matchcost <= insertcost && matchcost <= deletecost ) printpad ( m, s, t, i-1, j-1 ); if ( s [ i-1 ] == t [ j-1 ] ) // match cout << " M" << s [ i-1 ]; cout << " S" << s[i-1] << "->" << t[j-1]; // substitute if ( insertcost < deletecost ) printpad ( m, s, t, i, j-1 ); // eerst de voorgaande cout << " I" << t [ j-1 ]; // insert printpad ( m, s, t, i-1, j ); cout << " D" << s [ i-1 ]; // delete voorbeeld edit pad van "you should not murder" en "thou shalt not kill" Dt Sh y Mo Mu M_ Ms Mh Io Sa u Ml St d M_ Mn Mt M_ Im Iu Sk r Si d Sl w Sl r Dt delete t Sh y Substitute h by y Mo match o Io insert o 27 28 7

variaties op dit thema longest common subsequence lcs ( democrat, republican ) -> eca voldoende verandering: was 1 int match ( char c, char d ) return c==d? 0 : MAX ; maximum monotone subsequence mms ( 243517698 ) -> 23568 minste deletes om stijgende reeks te krijgen geen andere acties als past en delete meer variaties gelijkheid DNA-sequences Needleman/Wunsch score initieel 0 overeenkomst aminozuren: +2 verschil: -1 delete: -2 zoek de hoogste score ons algoritme zoekt de laagste kosten oplossing: voorzie alles van een min-teken 29 30 complexiteit we moeten een matrix helemaal vullen voor iedere cell wat werk met huidige letters: O ( 1 ) bekijk 3 buren: O ( 1 ) totaal voor één cell: O ( 1 ) voor hele matrix O ( n 2 ) héél veel beter dan de oorspronkelijke O ( 3 n ) geheugengebruik we gebruiken nu ook O ( n 2 ) geheugen als we het pad niet hoeven weten is dat vaak niet nodig voor edit diatance hebben we genoeg aan één rij 31 32 8

de pont de pont tussen Mook en Cuijk heeft een zeer smalle toegangsweg met 'n rij auto's hoe moeten we de auto's plaatsen (link of rechts) om er zoveel mogelijk op de pont te krijgen? int rij [] = 2,2,4,6,1,6,9,1,8,0 // de autolengtes int lengte = 20; // de rij lengte op de pont geeft einde aan 33 recursief algoritme geef resterende lengte linker en rechter rij mee a is index van te plaatsen auto = aantal auto's op pont resultaat is aantal auto's int plaats (int a=0, int l=lengte, int r=lengte ) if ( l<0 r<0 ) // laatste auto paste niet meer return -1; if ( rij [ a ] == 0 ( l == 0 && r == 0 )) return a; geen auto's meer beide rijen vol return max ( a // huidige aantal auto's, plaats (a+1, l - rij [ a ], r ) // auto links, plaats (a+1, l, r - rij [ a ] // auto rechts ); 34 analyse algoritme is dubbel recursief: O ( 2 n ) geschikt voor dynamic programming maak tabel met lengtes als index tabel bevat aantal te plaasten auto's we moeten nu wel voor iedere lengte de waarde uitrekenen eerst alleen voor de lengtes die je echt gebruikt 35 pont met dynamic programming int plaatsdp ( ) int **m = newint *[ Lengte+1 ]; for (int i=0; i<=lengte; i+=1 ) // maak ruimte voor tabel aan m [ i ] = newint [ Lengte+1 ]; for (int a=0, i=0; i<=lengte; a+=1 ) // vul randen for (int l=0; i<=lengte && ( l<rij [ a ] rij [ a ]==0 ); l++, i++ ) m [ 0 ] [ i ] = m [ i ] [ 0 ] = a; for (int i=1; i<=lengte; i+=1 ) // vul rest for (int j=1; j<=lengte; j+=1 ) l en i verhogen constint a = max ( m [ i-1 ] [ j ], m [ i ] [ j-1 ] ); constint l = rij [ a ]; if ( l>0 && ((i>=l && m[i-l][j]>=a) (j>=l && m[i][j-l]>=a)) ) m [ i ] [ j ] = a+1; m [ i ] [ j ] = a; return m [ Lengte ] [ Lengte ]; // lees resultaat uit tabel 36 9

de tabel int lengte = 20; 0 0 1 1 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 0 0 1 1 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 1 1 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 1 1 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 9 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 9 9 int rij [] = 2,2,4,6,1,6,9,1,8,0; 37 hou moeten de auto's staan? kan ook hier uit de tabel gelezen worden nu stappen zo groot als de auto lengte 38 pad door de tabel int lengte = 20; 0 0 1 1 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 0 0 1 1 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 1 1 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 1 1 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 2 2 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 2 2 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 2 2 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 2 2 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 3 3 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 3 3 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 3 3 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 3 3 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 3 3 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 3 3 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 4 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 5 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 5 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 5 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 9 5 6 6 6 6 6 6 6 6 6 7 8 8 8 8 8 8 8 8 9-9 int rij [] = 2,2,4,6,1,6,9,1,8,0; 39 vulling uit tabel in C++ void kant (int * m [ ], int i, int j ) constint a = m [ i ] [ j ]; if ( a>0 ) if ( i>0 && a == m [ i-1 ] [ j ] ) // skip lege plaatsten kant ( m, i-1, j ); if ( j>0 && a == m [ i ] [ j-1 ] ) // idem in andere richting kant ( m, i, j-1 ); if ( j-rij [ a-1 ] >= 0 && m [ i ] [ j-rij [ a-1 ]] == a-1 ) // past rechts? kant ( m, i, j-rij [ a-1 ] ); // eerst de voorgaande auto's cout << "auto " << a << " met lengte " << rij[a-1]<<" rechts\n"; // auto past zeker links kant ( m, i-rij [ a-1 ], j ); cout << "auto " << a << " met lengte " << rij[a-1] << " links\n"; 40 10

voorbeeld vulling int rij [] = 2,2,4,6,1,6,9,1,8,0; int lengte = 20; output: auto 1 met lengte 2 links auto 2 met lengte 2 rechts auto 3 met lengte 4 links auto 4 met lengte 6 links auto 5 met lengte 1 links auto 6 met lengte 6 links auto 7 met lengte 9 rechts auto 8 met lengte 1 rechts auto 9 met lengte 8 rechts algemeen deze techniek staat bekend als dynamic programming, of memoization algemeen: schrijf recursief algoritme herken termen die opnieuw uitgerekend worden stop die in een tabel lees uit tabel i.p.v. opnieuw rekenen werkt ook in veel gevallen waar je tot nu toe zou kiezen voor backtracken of breadth-first-search dit heeft veel betere complexiteit! 41 42 alternatief hier vullen we de hele tabel en lezen dan de uitkomst uit de tabel indien je niet alles nodig hebt kun je ook alleen opslaan wat je echt nodig hebt initieel: geen elementen een beginwaarde zorg dat je kunt zien dat je geen echte waarde hebt opgeslagen als je een waarde nodig hebt kijk in de tabel of die er is zo ja: gebruik de opgeslagen waarde zo nee: reken waarde uit en sla die op werk net zo goed, maar we zullen het niet verder uitwerken voorwaarden dynamisch programmeren wanneer werkt dit? recursief algoritme termen komen opnieuw voor er mogen geen globale afhankelijkheden zijn bovengrens aan tabel nodig hashing kan soms als er geen vaste bovengrens is 43 44 11

conclusies een directe recursieve implementatie is meestal duidelijk, maar kan een slechte complexiteit hebben zo n algoritme is vaak om te zetten naar een algoritme met betere complexiteit zorg dat berekening die vaker voorkomen en veelwerk zijn slechts één keer gedaan worden zie hoofdstuk 24 dictaat 45 12