Föreläsning 6. Rekursion och backtracking

Relevanta dokument
Föreläsning 6. Rekursion och backtracking

Föreläsning 4. Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö

Föreläsning 7. Träd och binära sökträd

Rekursion. Koffman & Wolfgang kapitel 5

Tentamen TEN1 HI

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

Datastrukturer i kursen. Föreläsning 8 Innehåll. Träd rekursiv definition. Träd

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

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

Tentamen, EDA501 Programmering M L TM W K V

Föreläsning 9 Innehåll

Föreläsning 7. Träd och binära sökträd

F11 - Rekursion. ID1004 Objektorienterad programmering Fredrik Kilander

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 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

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 2. Länkad lista och iterator

Föreläsning 13. Rekursion

Föreläsning 5. Rekursion

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

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

Föreläsning 8 Innehåll

Tentamen TEN1 HI

Föreläsning 5. Rekursion

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

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

Föreläsning 10. Grafer, Dijkstra och Prim

Föreläsning 10. Grafer, Dijkstra och Prim

Rekursion och induktion för algoritmkonstruktion

Abstrakt klass. DD2385 Programutvecklingsteknik Några bilder till föreläsning 4 31/ Exempel: Implementation av Schackpjäser.

Uppgifter föreslagna från vår kursbok markeras med avsnitt och sedan: SC Self Check, P Programing, PP Programing Projects.

Tentamen, EDA501/EDAA20 Programmering M MD W BK L

FÖRELÄSNING 11 DATALOGI I

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

Föreläsning 4 Innehåll

OOP Objekt-orienterad programmering

Tentamen, Algoritmer och datastrukturer

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

Abstrakt klass. DD2385 Programutvecklingsteknik Några bilder till föreläsning 4 7/ Exempel: Implementation av Schackpjäser.

Föreläsning 13. Dynamisk programmering

Lektion 2: Sökagenter. Robin Keskisärkkä

6 Rekursion. 6.1 Rekursionens fyra principer. 6.2 Några vanliga användningsområden för rekursion. Problem löses genom:

Föreläsning 11: Rekursion

Rekursion: varför? Problem delas upp i mindre bitar algoritm för att lösa problemet erhålls från problemformuleringen

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

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

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

Övningsuppgifter. Uppgifter föreslagna från vår kursbok markeras med avsnitt och sedan: SC Self Check, P Programing, PP Programing Projects.

Rekursion. Att tänka rekursivt Att programmera rekursivt i Java Exempel. Programmeringsmetodik -Java 254

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

TENTAMEN: Algoritmer och datastrukturer. Läs detta!

Trädstrukturer och grafer

Laboration A Objektsamlingar

Datastrukturer. föreläsning 3. Stacks 1

Föreläsning 9 Datastrukturer (DAT037)

Tentamen i Algoritmer & Datastrukturer i Java

7,5 högskolepoäng. Objektorienterad systemutveckling I Provmoment: Ladokkod: 21OS1B Tentamen ges för: Lycka till! /Peter & Petter

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

Tentamen Datastrukturer (DAT036)

Föreläsning Datastrukturer (DAT036)

Lösningsförslag tentamen FYTA11 Java

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Tentamen i Algoritmer & Datastrukturer i Java

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

Föreläsning 4 Datastrukturer (DAT037)

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

Föreläsning 8 Datastrukturer (DAT037)

Algoritmer och datastrukturer, föreläsning 11

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

Tentamen i Grundläggande Programvaruutveckling, TDA548

Lösningsförslag till tentamen i EDA011/EDA017 Programmeringsteknik för F, E, I, π och N 25 maj 2009

TENTAMEN I PROGRAMMERING. På tentamen ges graderade betyg:. 3:a 24 poäng, 4:a 36 poäng och 5:a 48 poäng

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

Tildatenta Lösningsskiss

Tentamen, EDAA20/EDA501 Programmering

Tentamen TEN1 HI

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Exempelduggan. Luffarschack. Koda spel

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

OBJEKTORIENTERAD PROGRAMVARUUTVECKLING. Övningstentamen 1

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

Föreläsning 6: Introduktion av listor

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

Tentamen Programmeringsteknik II Skrivtid: Hjälpmedel: Java-bok (vilken som helst) Skriv läsligt! Använd inte rödpenna!

Föreläsning 3. Stack

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

DD1320 Tillämpad datalogi. Lösning (skiss) till tenta 20 okt 2011

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren att du har förstått dessa även om detaljer kan vara felaktiga.

Föreläsning 1, vecka 7: Rekursion

Lösningsförslag till exempeltenta 1

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

Tentamen för kursen Objektorienterad programvaruutveckling GU (DIT010)

Algoritmanalys. Genomsnittligen behövs n/2 jämförelser vilket är proportionellt mot n, vi säger att vi har en O(n) algoritm.

Tentamen'('Datastrukturer,'algoritmer'och'programkonstruktion.'

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

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

Objektorienterad programmering

Malmö högskola 2007/2008 Teknik och samhälle

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

Tentamen Datastrukturer, DAT037 (DAT036)

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

Transkript:

Föreläsning 6 Rekursion och backtracking

Föreläsning 6 Bredden först med hjälp av kö Lista rekursivt Tornet i Hanoi Backtracking Läsanvisningar och uppgifter

Hissen i lustiga huset Huset har n antal våningar (bottenvåningen som räknas som en av dessa kallas våning 1). Hissen har två knappar: den ena skickar upp hissen upp antal våningar om möjligt, den andra skickar ned hissen ned antal våningar om möjligt. Om man befinner sig på bottenvåning hur många resor måste man då göra för att komma till våning destination? Skriv en rekursiv funktion som tar reda på minsta antalet resor för valfritt värde på variablerna n, upp, ned och destination. Exempel: n=78, upp=15, ned=8, destination=35 ger minsta antalet resor till 13

Skal static int antalresorhiss(int n, int upp, int ned, int position, int destination, int antalresor) { //kod } static int antalresorhiss(int n, int upp, int ned, int destination) { return antalresorhiss(n,upp,ned,1,destination,0); }

Förslag static int antalresorhiss(int n, int upp, int ned, int position, int destination, int antalresor) { if(position==destination) return antalresor; else if(antalresor>30) //behövs den? Vad händer annars? return Integer.MAX_VALUE; else{ int antalupp=integer.max_value,antalned=integer.max_value; if(position+upp<=n) antalupp = antalresorhiss(n,upp,ned,position+upp,destination,antalresor+1); if(position-ned>=1) antalned = antalresorhiss(n,upp,ned,position-ned,destination,antalresor+1); return Math.min(antalUpp, antalned); } }

upp 1 ner Djupet först 4 7 3 Låt oss titta på vad som händer i ett enkelt exempel: n = 7, upp = 3, ned = 1, destination = 2 Vårt program kommer åka: 1,4,7,6,5,4,7,6,5,4,7,osv Här måste vi sätta ett maxdjup för att komma fram. Är vi ute efter den kortaste resvägen blir denna genomsökning mycket ineffektiv. Det vore bättre att söka igenom trädet nivå för nivå istället. Då vet vi direkt när vi hittar en lösning att det är en av de bästa. 6 6 2 5 4 7 6 5

Djupet kontra bredden först

Bredden först Anledningen att vi får djupet först i vår rekursiva lösning är att våra funktionsanrop hamnar på en stack där det gäller att Last In First Out. Om vi vill söka igenom lösningsträdet med bredden först behöver vi, just det en kö! Stacken har vi så att säga gratis. Kön måste vi hantera själva.

n=1. Köa upp (4). Kö: 4 Bredden först med hissen Avköar n=4. Vi köar upp (7) och ner (3). Kö: 7, 3 Avköar n=7. Vi köar ner (6) Kö: 3, 6 Avköar n=3. Vi köar upp (6) och ner (2) Kö: 6, 6, 2 Avköar n=6. Vi köar ner (5) Kö: 6, 2, 5 Avköar n=6. Vi köar ner (5) Kö: 2, 5, 5 Avköar n=2. 1 upp 2 1 ner 3 4 4 7 5 3 6 7 6 6 2

Hur köar vi en plats i trädet? De data som är relevanta för en plats i trädet är vilken våning befinner vi oss på och hur många resor vi har gjort. För att kunna köa platser i trädet behöver vi alltså kunna hålla reda på dessa data. Enklast skapar vi en klass: private static class Tillstand{ public int position,antalresor; public Tillstand(int p, int a){ position=p; antalresor=a; } }

Kod för hissen med bredden först static int antalresorbredd(int n, int upp, int ned, int destination){ Queue<Tillstand> q = new LinkedList<Tillstand>(); Tillstand t = new Tillstand(1,0); while(t.position!=destination){ if(t.position+upp<=n) q.offer(new Tillstand(t.position+upp,t.antalResor+1)); if(t.position-ned>=1) q.offer(new Tillstand(t.position-ned,t.antalResor+1)); t=q.poll(); } } return t.antalresor; observera hur lätt vi kunde skriva om problemet till iteration tack vare kön

Rekursiv tostring i vår länkade lista Många metoder vi skrivit skulle med fördel kunnat skrivas rekursivt: private void tostringrec(stringbuilder sb,node p){ sb.append(p.data.tostring()); if(p.next!=null){ sb.append(" ==> "); tostringrec(sb,p.next); } } public String tostringrec(){ StringBuilder sb = new StringBuilder("["); if(head!=null) tostringrec(sb,head); sb.append("]"); return sb.tostring(); }

eller ännu enklare private String tostringrecsimple(node p){ if(p.next!=null) return p.data.tostring()+" ==> "+tostringrecsimple(p.next); return p.data.tostring(); } public String tostringrecsimple(){ if(head!=null) return "["+tostringrecsimple(head)+"]"; return "[]"; }

Rekursiv länkad lista Det är inte bara metoderna i våra datastrukturer som kan skrivas rekursiva utan datastrukturer kan definieras rekursivt. En länkad lista kan definieras rekursivt enligt: En länkad lista är antingen tom eller består av en nod med en referens till ett data och en referens till en länkad lista. Fler rekursiva implementeringar finns i boken

Tornet i Hanoi n brickor ska flyttas från pinne 1 till pinne 2. Man får bara flytta en bricka i taget och bara översta brickan i en hög. En bricka får aldrig ligga på en mindre bricka 1 2 3

Algoritm Flytta n brickor från f till t (x tredje) Om n>0 flytta n-1 brickor från f till x flytta 1 bricka från f till t flytta n-1 brickor från x till t 1 2 3

Kod static void hanoi(int n, int f, int t, int x){ if(n>0){ hanoi(n-1,f,x,t); System.out.println(f+"->"+t); hanoi(n-1,x,t,f); } } anrop:hanoi(3,1,2,3) Hur skulle du skriva en iterativ lösning?

Analys T(0) = 0 T(n) = 2T(n-1) + 1 n 1 2 3 4 5 6 T(n) 1 3 7 15 31 63 T(n) = 2 n 1 = O(2 n ) Enligt legenden skulle världen gå under när munkarna hade gjort tornet med 64 brickor: (2 64 1) s = 585 miljarder år

Backtracking Backtracking är en klass algoritmer som bygger upp lösningskandidater till ett problem steg för steg och överger en kandidat så fort den inte längre kan vara en lösning och då backar ett steg för att hitta en ny lösningskandidat. Detta gör den på ett sådant sätt att den aldrig prövar samma kandidat två gånger. Backtracking är ofta den enklaste om än inte mest effektiva lösningen till problem såsom sudoku, labyrint, korsord, schack och åtta damer.

Backtracking i en labyrint Gå så långt du kan tills du kommer ut eller det tar stopp. Om det tar stopp backa till närmsta förgrening och prova en annan väg du inte har provat. Om du provat alla backa ännu längre till nästa förgrening och prova en annan väg du inte har provat. osv

Algoritm Vi ska här representera en labyrint som ett rutnät där varje ruta antingen är en vägg eller öppen. En av de öppna rutorna är dessutom start och en är mål. hittaut(ruta) Markera ruta som korrekt väg Om ruta är målet returnera true annars Om ruta ovanför är öppen och obesökt Om hittaut(ruta ovanför) returnera true Om ruta till höger är öppen och obesökt Om hittaut(ruta till höger) returnera true Om ruta nedanför är öppen och obesökt Om hittaut(ruta nedanför) returnera true Om ruta till vänster är öppen och obesökt Om hittaut(ruta till vänster) returnera true Markera ruta som besökt returnera false

Primitivt skal För att algoritmen ska fungera krävs att vi har vägg runt hela kanten utom vid målet. Ofta vill man ha starten precis vid kanten också och då kommer vår algoritm att riskera att försöka gå direkt ut ur labyrinten. För att slippa lägga till randkontroller i algoritmen har jag därför lagt till väggar runt hela labyrinten. På kth-social finns ett primitivt skal som läser in en labyrint från en textfil. Kvar är att skriva in själva algoritmen.

Åtta damer Detta klassiska problem går ut på att placera 8 damer på ett schackbräde så att ingen dam står på samma rad, kolumn eller diagonal som en annan. På bilden ser du en sådan lösning. Vi ska skriva ett program som hittar alla lösningar med hjälp av backtracking.

Skissa på en algoritm Den ska prova sig framåt tills det inte går. Då ska den backa till ett ställe där den har fler alternativ. Den kommer att vara rekursiv. Tips. Ställ en dam på varje rad, en rad i taget. Ställ varje dam så att den står korrekt.

Algoritm addqueen(rad) för kolumn 1 till 8 om kolumn möjlig boka platsen om rad==8 skriv ut lösning annars addqueen(rad+1) avboka platsen Anropas då med addqueen(1)

Listiga tricks Vi kan välja en 2d boolean matris som enda datastruktur och markera en drottning med true men det blir hyggligt jobbigt att kontrollera om en viss plats är möjlig. Enklare då att förutom 2d-matrisen ha en array column, en array nediagonal och en array nwdiagonal som håller reda på om dessa är upptagna. Om column[3] är true betyder det då att den tredje kolumnen är upptagen. Med diagonalerna är det lite trickigare. Om nediagonal[4] är true betyder att den diagonal där rad+kolumn=4 är upptagen och om nwdiagonal[4] är true betyder det att den diagonal där rad-kolumn=4-7=-3 är upptagen. För ne lagras alltså diagonalerna på plats rad+kolumn och för nw lagras alltså diagonalerna på plats rad-kolumn+7.

Läsanvisningar och uppgifter KW 5.4, 5.5, 5.6 Uppgifter: NB 20 (1p), 21, 22 (1p), 23 (1p), 24, 25 (2p)

Uppgifter NB 20 (1p) Skriv en ny lösning till myntmaskinen NB 16 som löser problemet med bredden först istället för djupet först. Varför är det egentligen inte nödvändigt för det här problemet?

NB 21 Skriv om några funktioner till vår länkade lista så att de blir rekursiva. Hjälp finns i boken men försök själv.

NB 22(1p) Utgå från skalet som finns på kth-social och använd backtracking för att skriva klart funktionen solve så att programmet presenterar en lösning till inläst labyrint. Prova programmet på några labyrinter som du har klara till presentationen.

NB 23 (1p) Åtta damer Skriv ett program som löser åtta damer problemet och presenterar alla lösningar Skriv en ny version av programmet som löser n-damer problemet. Hur ställer man n damer på ett n*n bräde så att ingen står på samma rad, kolumn eller diagonal. Användaren ska få ange n och sedan få veta hur många lösningar det finns. Programmet ska inte skriva ut lösningarna.

NB 24 a) I ett enkelt brickspel ligger svarta och vita brickor enligt fig 1. Målet är att få brickorna enligt fig 2. Tillåtna drag är att flytta en bricka ett steg till en tom ruta eller hoppa över en bricka till en tom ruta (fig 3). Skriv ett program som beräknar dragföljden för att lyckas på 15 drag och presenterar den såsom: 3->4, 5->3 osv b) Lös hissproblemet med backtracking

NB 25 (2p) Skriv ett program som hittar alla lösningar till pusslet ovan. För att lösa det har man 8 likadana pusselbitar som kan vridas så att man får de fyra varianterna ovan. Den grå rutan skall inte täckas. Lägg sedan till så att användaren får möjlighet att ange vilken ruta som ska vara grå och programmet ska då beräkna antalet möjliga lösningar. I exemplet ovan har användaren då angett 1,3.