Exempel: Förel Rekursion III Nr 14. Uno Holmer, Chalmers,

Relevanta dokument
Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Föreläsning 8 Innehåll

Rekursion och induktion för algoritmkonstruktion

Rekursion. Koffman & Wolfgang kapitel 5

Den som bara har en hammare tror att alla problem är spikar

String [] argv. Dagens Agenda. Mer om arrayer. Mer om arrayer forts. String [] argv. argv är variabelnamnet. Arrayer och Strängar fortsättning

Föreläsning 6. Rekursion och backtracking

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Föreläsning 11: Rekursion

Föreläsning 6. Rekursion och backtracking

Föreläsning 3-4 Innehåll

Rekursion och induktion för algoritmkonstruktion

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Föreläsning 6 Innehåll. Rekursion. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursiv problemlösning. Rekursion. Rekursivt tänkande:

public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

Föreläsning 1, vecka 7: Rekursion

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

Tentamen, EDA501 Programmering M L TM W K V

Objektorienterad programmering E. Back to Basics. En annan version av printtable. Ett enkelt exempel. Föreläsning 10

Föreläsning 13. Dynamisk programmering

ITK:P1 Föreläsning 1. Programmering. Programmeringsspråket Java. Stark typning Explicit typning Strukturerat Hög säkerhet

Hitta k största bland n element. Föreläsning 13 Innehåll. Histogramproblemet

EDAA20 Föreläsning Klassen ArrayList. Viktiga operationer på ArrayList. Generisk klass

Tentamen. Datalogi I, grundkurs med Java 10p, 2D4112, Lördagen den 30 november 2002 kl , salar E33, E34

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Föreläsning 1 Datastrukturer (DAT037)

Datastrukturer. föreläsning 3. Stacks 1

Metodanrop - primitiva typer. Föreläsning 4. Metodanrop - referenstyper. Metodanrop - primitiva typer

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Rekursion och induktion för algoritmkonstruktion

Föreläsning 4 Innehåll. Abstrakta datatypen lista. Implementering av listor. Abstrakt datatypen lista. Abstrakt datatyp

4 13 / %.; 8 </" '': " / //&' " " ' * TelefonKostnad +,-%&. #!" $% " &' . > / ' 5 /' * 13/ &' static Math 1+" &'/ % 12 "" static "' * 1 /") %& &

Föreläsning 10. ADT:er och datastrukturer

Lösning av några vanliga rekurrensekvationer

Föreläsning 13. Dynamisk programmering

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

FÖRELÄSNING 2, TDDC74, VT2018 BEGREPP PROBLEMLÖSNING MED HJÄLP AV FALLANALYS PROBLEMLÖSNING MED HJÄLP AV REKURSION

Föreläsning 13. Rekursion

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Programmering för språkteknologer II, HT2011. Rum

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

F11 - Rekursion. ID1004 Objektorienterad programmering Fredrik Kilander

Tentamen i Algoritmer & Datastrukturer i Java

OOP Objekt-orienterad programmering

Föreläsning 5&6 LOGISKA VARIABLER; IMPLEMENTERA KLASSER; MER ALGORITMER

Tentamen, EDAA20/EDA501 Programmering

Lösningsförslag till exempeltenta 1

Föreläsning 3: Booleans, if, switch

Objektorienterad Programmering (TDDC77)

Föreläsning 4 Datastrukturer (DAT037)

ADT Kö. Seminarium 4 Köer och Stackar Innehåll. Operationer. ADT Stack. Definition. Definition

Föreläsning 1: Dekomposition, giriga algoritmer och dynamisk programmering

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning 2. Länkad lista och iterator

Föreläsning 5. Rekursion

Lösningsförslag till exempeltenta 2

OOP Objekt-orienterad programmering

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Outline. I Vi kan lätt göra samma sak för fyra variabler... I Hur gör vi för 400 inlästa värden? I Ofta behöver man flera likadana variabler

Tentamen, Algoritmer och datastrukturer

F5 Selektion och iteration. ID1004 Objektorienterad programmering Fredrik Kilander

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

Påminnelse: en datatyp för bilder. Programmering. En datatyp för bilder. Spegelbild. hh.se/db2004

Föreläsning 4 Innehåll

TDDD78 Viktiga begrepp, del 2

Föreläsning 2 Datastrukturer (DAT037)

Föreläsning 8: Exempel och problemlösning

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

Tommy Färnqvist, IDA, Linköpings universitet

Algoritmer, datastrukturer och komplexitet

Algoritmer och datastrukturer H I HÅKAN S T R Ö M B E R G N I C K L A S B R A N D E F E L T

Tentamen. Lösningsförslag

Del A (obligatorisk för alla)

Föreläsning ALGORITMER: SÖKNING, REGISTRERING, SORTERING

Föreläsning 5 Innehåll

Föreläsning 2 Datastrukturer (DAT037)

Tentamen, EDA501/EDAA20 Programmering M MD W BK L

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista

JAVAUTVECKLING LEKTION 8

i=1 c i = B och c i = a i eller c i = b i för 1 i n. Beskriv och analysera en algoritm som löser detta problem med hjälp av dynamisk programmering.

Sökning och sortering

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Objektorienterad Programmering (TDDC77)

Föreläsning 11 Datastrukturer (DAT037)

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Programmering för språkteknologer II, HT2011. Rum

Tentamen, EDAA20/EDA501 Programmering

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Inlämningsuppgiften. Föreläsning 9 Innehåll. Träd. Datastrukturer i kursen

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Lösningsförslag till tentamen i EDA011, lördagen den 16 december 2006

Tentamen, EDAA10 Programmering i Java

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

TENTAMEN OOP

Ekvivalensrelationer

Föreläsning 3. Stack

Transkript:

Exempel: Kappsäcksproblemet Backtracking Dynamisk programmering Föreläsning (Weiss kap..-) Kan man ur en grupp föremål F,,F N med vikterna V,,V N välja ut en delgrupp som väger exakt M kilo? Exempel: föremål vikt Snåla algoritmer Backtracking Exempel: Kappsäcksproblemet, labyrintsökning Dynamisk programmering Man kan packa till alla totalvikter upp till kilo utom till vikterna,, och 0 F F F F F Snåla algoritmer En snål (eng. greedy) algoritm väljer den för tillfället optimala lösningen utan hänsyn till framtida konsekvenser. Exempel: En snål strategi för kappsäcksproblemet vore att prova vikterna i avtagande följd. Metoden löser inte problemet givet uppsättningen på föregående bild för t.ex. totalvikten kg. Varför inte? Problemet kan dock lösas med en snål algoritm om vikterna är tvåpotenser,,, 8,, Rekursiv algoritmidé Kappsäcksproblemet kan lösas rekursivt: Antag att vi skall packa upp till M kilo med föremål ur samlingen F,,F N Fallanalys: (- är basfallen). Om kappsäcken väger M kilo har vi löst problemet.. Om kappsäcken väger mer än M kilo har vi misslyckats.. Om det finns mer plats men inte fler föremål har vi misslyckats. återstår två fall: (rekursionssteget). Vi tar med F N och försöker packa resterande utrymme med F,,F N-. Vi slänger F N och försöker packa resterande utrymme med F,,F N- Förenkla problemet genom att bara betrakta vikterna V,,V N Låt S beteckna packningens vikt Problemet är att avgöra om det finns en delvektor i V,,V N vars summa är M. Generalisering: Definiera predikatet packa(s, M, V,,V N ) som är sant om det finns en delvektor i V,,V N vars summa är M - S och falskt annars Definiera packa(s, M, V,,V N ) rekursivt: Basfallen:. Returnera sant om S = M. Returnera falskt om S > M. Returnera falskt om S < M och N = 0 Rekursionssteg: S < M och N > 0. Lös problemet för utrymmet M - S och vikterna V,,V N Rekursionsantagande: Antag att packa(x, M, V,,V N- ) löser problemet för ett godtyckligt X S samt vikterna V,,V N-

Med stöd av rekursionsantagandet kan vi anta att: packa(s + V N, M, V,,V N- ) löser problemet för fallet då V N tas med och att packa(s, M, V,,V N- ) löser problemet för fallet då V N slängs Alltså: returnera SANT för S och V,,V N om packa(s + V N, M, V,,V N- ) eller packa(s, M, V,,V N- ) returnerar SANT. Implementering i Java boolean packa( int S, int M, int[] V, int N ) if ( S == M ) if ( S > M N == 0 ) return false; return packa( S + V[ N - ], M, V, N - ) packa( S, M, V, N - ); 8 Vilka vikter löste problemet? En vikt får bara skrivas ut när vi vet att den bidrar till lösningen. boolean packa( int S, int M, int[] V, int N ) if ( S == M ) if ( S > M N == 0 ) return false; if( packa( S + V[ N - ], M, V, N - ) ) System.out.print( V[ N - ] ); return packa( S, M, V, N - ); Backtracking Att lösa ett problem genom att rekursivt prova alla möjligheter. I varje rekursionssteg väljs den bästa dellösningen. Exempel Labyrint Tic-Tac-Toe se Weiss. 9 0 Exempel: Labyrintsökning Givet: En rektangulär labyrint L med ickecykliska gångar 8 9 8 9 0 Tre olika sökproblem Resultat. Finns det en utväg från (x,y)? Ja/Nej. Skriv ut en utväg från (x,y) en väg. Skriv ut den kortaste utvägen från (x,y) optimal väg En position (cell) i labyrinten är antingen golv eller vägg (svart) Gångarna har bredden Förflyttning sker stegvis en cell i taget vågrätt eller lodrätt

Genom att ta ett steg kommer vi in i en dellabyrint. (Man backar bara till en cell för att prova en annan riktning.) Ett steg uppåt från (,) tar oss till dellabyrinten (L ) 8 9 0 Divide & Conquer Problemet att hitta ut från (,) i L kan delas upp rekursivt i delproblemen att hitta ut via (,) i L eller via (,) i L, eftersom vi kan nå L och L i ett steg De tre problemen. Det finns en väg ur L om det finns en väg ur L, eller en väg ur L. Skriv ut en väg via L, eller en via L Ett steg nedåt från (,) tar oss till dellabyrinten (L ) 8 9 0 8 9. Skriv ut den kortaste av vägarna via L resp. L Basfall: a) Återvändsgränd b) Ute Rekursionsantagande: Sökalgoritmen kan avgöra problemet för dellabyrinterna Pseudoalgoritm boolean finnsutväg( pos, labyrint ) om pos är utanför labyrinten returnera SANT annars för varje riktning r p' = steg( pos, r ) om ärtillåtetsteg från pos till p' och finnsutväg( p', labyrint ) returnera SANT returnera FALSKT Klassen Labyrint public class labyrint public Labyrint( String filnamn ); public void hittaut (Position startpos )... private boolean ärutanför( Position p )... private Position steg( Position p, Riktning r )... private boolean ärtillåtetsteg( Position gpos,position pos, Riktning rikt )... private boolean sök ( Position gpos, Position pos )... private boolean ärgolv( Position p )... private char[][] labyrinten; private int bredd, höjd; Datatyper för positioner och riktningar public class Position public Position( int rad, int kolumn ) this.rad = rad; this.kolumn = kolumn; public boolean equals( Position rhs ) return ( rad == rhs.rad && kolumn == rhs.kolumn ); public int rad, kolumn; ; public enum Riktning VÄNSTER, UPP, HÖGER, NER Tre användbara operationer boolean ärutanför( Position pos ); // avgör om pos är utanför labyrinten eller ej Position steg( Position pos, Riktning riktning ); // returnerar positionen man kommer till // genom ett steg från pos i angiven riktning bool tillåtetsteg( Position gpos, Position pos, Riktning riktning ); // avgör om ett steg från pos i angiven riktning // leder utanför labyrinten, eller till en annan // golvposition än gpos 8

Ett steg i rätt riktning? Metoden ärutanför gpos vi gick härifrån... Nix backa! rikt sök boolean ärutanför( Position p ) return p.rad < 0 p.rad >= höjd p.kolumn < 0 p.kolumn >= bredd; pos...och hit steg(pos,rikt) kan vi gå dit? 9 0 Metoden steg Metoden ärtillåtetsteg Position steg( Position p, Riktning r ) switch ( r ) case VÄNSTER: return new Position( p.rad, p.kolumn - ); case HÖGER: return new Position( p.rad, p.kolumn + ); case NER: return new Position( p.rad +, p.kolumn ); case UPP: return new Position( p.rad -, p.kolumn ); boolean ärtillåtetsteg( Position gpos, Position pos, Riktning rikt ) Position nypos = steg( pos, rikt ); return ärutanför( nypos ) ( labyrinten[nypos.rad][nypos.kolumn] == golv &&! nypos.equals( gpos ) ); Metoden hittaut Metoden Sök void hittaut( Position startpos ) if ( sök( startpos, startpos ) ) System.out.print( "det finns en utväg ); boolean sök( Position gpos, Position pos ) for ( Riktning riktning : Riktning.values() ) if ( ärtillåtetsteg( gpos, pos, riktning ) && sök( pos, steg( pos, riktning ) ) ) return false; // inlåst!?

Hur skriver man ut vägen? Metoden hittautväg När kan man tidigast skriva ut information om vägen? Hur räknar man ut den kortaste vägen? void hittautväg( Position startpos ) if (! sökutväg( startpos, startpos ) ) Metoden sökutväg boolean sökutväg( Position gpos, Position pos ) for ( Riktning riktning : Riktning.values() ) if ( ärtillåtetsteg( gpos, pos, riktning ) && sökutväg( pos, steg( pos, riktning ) ) ) System.out.print( riktning ); return false; // inlåst!? Hur skriver man ut vägen rättvänd? Lägg riktningarna på en stack istället för att skriva ut dem under sökningen Skriv ut innehållet i stacken när sökningen är klar 8 Metoden hittarättutväg void hittarättutväg( Position startpos ) Stack<Riktning> vägen; if ( sökrättväg( startpos, startpos, vägen ) ) while (! vägen.isempty() ) skrivriktning( vägen.peek() ); vägen.pop(); Metoden sökrättväg boolean sökrättväg( Position gpos, Position pos, Stack<Riktning> vägen ) for ( Riktning riktning : Riktning.values() ) if ( ärtillåtetsteg( gpos, pos, rikt ) && sökrättväg( pos, steg( pos, rikt ), vägen ) ) vägen.push( rikt ); return false; 9 0

Hur finner man den kortaste vägen? Inför en speciell datatyp för vägar Operationer: returnera vägens längd: längd() lägg till en riktning: add skriv ut vägen: print() Klassen Väg class Väg public Väg() längden = Integer.MAX_VALUE; vägen = new LinkedList(); public int längd() return längden; public Väg add( Riktning r )... public void print()... private LinkedList<Riktning> vägen; private int längden; ; // Antag oändligt lång // Ger en ny väg inkl. r // FIFO-kö Metoden hittakortastevägen Metoden sökkortastevägen void hittakortastevägen( Position startpos ) Väg kortastevägen = sökkortastevägen( startpos, startpos, new Väg() ); if ( kortastevägen.längd() < Integer.MAX_VALUE ) kortastevägen.print(); Väg sökkortastevägen( Position gpos, Position pos, Väg vägen ) return vägen; Väg kortast, aktuell; for ( Riktning riktning : Riktning.values() ) if ( ärtillåtetsteg( gpos, pos, rikt ) ) aktuell = sökkortastevägen( pos, steg( pos, rikt ), vägen.add( rikt ) ); if ( aktuell.längd() < kortast.längd() ) kortast = aktuell; return kortast; Dynamisk programmering Problemet En rekursiv D&C-algoritm som löser många överlappande delproblem blir orimligt ineffektiv Dynamisk programmering Lösningarna på delproblemen sätts successivt in i en tabell. Inget delproblem löses flera gånger. Metoden kräver extra minne men kan i gengäld bli avsevärt effektivare än en naiv D&C-algoritm. Exempel: se Weiss. Ex. fibonaccital med dynamisk programmering fibtable 0 Hämta värdet från tabellen om n 8 Tekniken kallas memoization Komplettera tabellen om n >

public class MemoizingFib private long[] fibtable; int highfibindex; Implementering i Java Komplexitet trade off: tid - minne public MemoizingFib(int size) fibtable = new long[size]; fibtable[0] = fibtable[] = ; highfibindex = ; T(N) = tidsåtgång M(N) = minnesbehov för beräkning av det N:te fibonaccitalet public long fib(int n) if ( n >= fibtable.length ) // allocate a bigger table and copy elements if ( n > highfibindex ) fibtable[n] = fib(n-) + fib(n-); highfibindex = n; public static void main(string[] args) return fibtable[n]; MemoizingFib mf = new MemoizingFib(00); for ( int n = 0; n < 00; n++ ) System.out.println(mf.fib(n)); WC AC Iterativ fib Naiv rekursiv fib Memoiserande fib T(N) = O(N) M(N) = O() T(N) = O( N ) M(N) = O(N) T(N) = O(N) M(N) = O(N) T(N) = O() M(N) = O(N) 8