Backtracking som løsningsmetode

Like dokumenter
Backtracking som løsningsmetode

Backtracking: Kombinatorikk og permutasjoner

Kapittel 3: Kombinatorikk

Kapittel 3: Kombinatorikk

Forelesning 6, kapittel 3. : 3.6: Kombinatorikk.

En algoritme for permutasjonsgenerering

INF1010. Sekvensgenerering Alle mulige sekvenser av lengde tre av tallene 0, 1 og 2: Sekvensgenerering. Generalisering. n n n! INF1010 INF1010 INF1010

INF2220: Forelesning 7. Kombinatorisk søking

Hva er en stack? En lineær datastruktur der vi til enhver tid kun har tilgang til elementet som ble lagt inn sist

Hva er en stack? En lineær datastruktur der vi til enhver tid kun har tilgang til elementet som ble lagt inn sist

UNIVERSITETET I OSLO

N-dronningproblemet Obligatorisk oppgave 1 I120, H-2000

PG 4200 Algoritmer og datastrukturer Innlevering 1. Frist: 2.februar kl 21.00

IN2010: Forelesning 11. Kombinatorisk søking Beregnbarhet og kompleksitet

Sannsynlighetsregning

Stack. En enkel, lineær datastruktur

INF1010 Rekursjon. Marit Nybakken 1. mars 2004

Sudokubrettet Et sudokubrett består av n n ruter. Vi bruker følgende begreper i oppgaven:

Obligatorisk oppgave 5: Labyrint

IN1010 V18, Obligatorisk oppgave 5

Rekursjon. Binærsøk. Hanois tårn.

Søkeproblemet. Gitt en datastruktur med n elementer: Finnes et bestemt element (eller en bestemt verdi) x lagret i datastrukturen eller ikke?

INF1010 Sortering. Marit Nybakken 1. mars 2004

Datastrukturer for rask søking

Norsk informatikkolympiade runde

Rekursiv programmering

Rekursjon som programmeringsteknikk

Grunnleggende Grafalgoritmer II

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

"behrozm" Oppsummering - programskisse for traversering av en graf (dybde først) Forelesning i INF februar 2009

Sorteringsproblemet. Gitt en array A med n elementer som kan sammenlignes med hverandre:

Hvorfor sortering og søking? Søking og sortering. Binære søketrær. Ordnet innsetting forbereder for mer effektiv søking og sortering INF1010 INF1010

Binære trær: Noen algoritmer og anvendelser

ITF20006 Algoritmer og datastrukturer Oppgavesett 7

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

PG 4200 Algoritmer og datastrukturer Innlevering 2

Eksamen iin115, 14. mai 1998 Side 2 Oppgave 1 15 % Du skal skrive en prosedyre lagalle som i en global character array S(1:n) genererer alle sekvenser

EKSAMEN. Emne: Algoritmer og datastrukturer

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

E K S A M E N. Algoritmiske metoder I. EKSAMENSDATO: 11. desember HINDA / 00HINDB / 00HINEA ( 2DA / 2DB / 2EA ) TID:

Heap* En heap er et komplett binært tre: En heap er også et monotont binært tre:

Sudokubrettet Et sudokubrett består av n n ruter. Vi bruker følgende begreper i oppgaven:

TDT4100 Objektorientert programmering

Norsk informatikkolympiade runde

Quicksort. Fra idé til algoritme.

Dagens temaer. Sortering: 4 metoder Søking: binærsøk Rekursjon: Hanois tårn

Vi skal se på grafalgoritmer for:

Rekursjon. Hanois tårn. Milepeler for å løse problemet

Løsnings forslag i java In115, Våren 1996

Algoritmer og Datastrukturer

IN1010 våren januar. Objektorientering i Java

Algoritmer og datastrukturer Kapittel 1 - Delkapittel 1.3

LØSNINGSFORSLAG, EKSAMEN I ALGORITMER OG DATASTRUKTURER (IT1105)

INF1010 våren januar. Objektorientering i Java

Programmering Høst 2017

Sudokubrettet Et sudokubrett består av n n ruter. Vi bruker følgende begreper i oppgaven:

Eksamen IN1010/INF1010 våren 2018

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

Definisjon av binært søketre

BOKMÅL Side 1 av 6. EKSAMEN I FAG TDT4102 Prosedyre og objektorientert programmering. Fredag 6. juni 2008 Kl

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

EKSAMEN. Dato: 18. mai 2017 Eksamenstid: 09:00 13:00

Norsk informatikkolympiade runde

Logaritmiske sorteringsalgoritmer

Kombinatorisk søking, rekursjon, avskjæring

Definisjon: Et sortert tre

På tide med et nytt spill! I dag skal vi lage tre på rad, hvor spillerne etter tur merker ruter med X eller O inntil en av spillerne får tre på rad.

UNIVERSITETET I OSLO

INF1010 notat: Binærsøking og quicksort

Algoritmer - definisjon

Binær heap. En heap er et komplett binært tre:

Algoritmer og Datastrukturer

Algoritmer og Datastrukturer

Løsnings forslag i java In115, Våren 1998

Algoritmer og Datastrukturer

INF1010. Rekursjon En rekursiv definisjon av rekursjon, slik det kunne stå i en ordbok: Introduksjon til Rekursiv programmering

Oblig2 - obligatorisk oppgave nr. 2 (av 4) i INF1000 v2008

Algoritmer og datastrukturer Løsningsforslag

IN1000 Obligatorisk innlevering 7

INF2220: Time 8 og 9 - Kompleksitet, beregnbarhet og kombinatorisk søk

Repetisjon: operatorene ++ og -- Java 5. Nøtt. Oppgave 1 (fra forrige gang) 0 udefinert udefinert. Alternativ 1 Prefiks-operator

EKSAMENSFORSIDE Skriftlig eksamen med tilsyn

Norsk informatikkolympiade runde. Sponset av. Uke 46, 2017

Transkript:

Backtracking

Backtracking som løsningsmetode Backtracking løser problemer der løsningene kan beskrives som en sekvens med steg eller valg Kan enten finne én løsning eller alle løsninger Bygger opp løsningen(e) ett steg om gangen: Prøver etter hvert steg alle mulige steg videre Hvis vi ser at et steg ikke kan lede til en løsning stopper vi videre utbygging av løsningen (avskjæring) Tar da et steg tilbake (backtracking) og prøver i stedet neste mulige steg som kan lede til løsning

Backtracking vs. brute force Rå kraft (brute force) algoritmer: Genererer alle mulige sekvenser av steg som kan være en løsning For hver av de mulige løsningene: Sjekk om den er korrekt Ressurskrevende, ubrukelig for større problemer Algoritmer med backtracking: Er ofte basert på en rå kraft algoritme Stopper oppbyggingen av en mulig løsning når vi ser at den ikke kan være korrekt Effektiviteten avhenger av hvor smart/tidlig vi gjør denne avskjæringen av løsninger

Backtracking og rekursjon Backtrackingsalgoritmer er av natur rekursive: Vi tar et og et steg mot en fullstendig løsning I hvert steg løser vi det samme problemet Problemstørrelsen reduseres for hvert steg Bunnen i rekursjonen: Vi har bygget opp en komplett løsning og det er ikke flere steg igjen å ta

Problemeksempler Finne en korrekt rekkefølge: Dronningproblemet Fargelegging av kart Fordeling av ressurser iht. behov eller ønsker Løsning av kryssord, sudoku, brettspill Rutevalg: Finne beste vei gjennom et nettverk Labyrinter

Enkelt eksempel: En labyrint Kvadratisk rutenett der noen ruter er blokkerte Starter i øvre venstre hjørne, prøver å finne vei til nedre venstre hjørne Fire muligheter i hvert steg: Høyre, ned, venstre, opp Avskjæring: Går ikke ut av labyrinten Går ikke til blokkerte ruter Går ikke til ruter som er besøkt tidligere

Datastruktur for labyrinten Setter opp labyrinten som en todimensjonal tabell med heltall, med verdiene 1 (fri) og 0 (stengt) Mens algoritmen utføres: Markerer oppsøkte ruter med verdien 2 i tabellen Tar vare på veien, ved at ruter som ligger på funnet vei markeres med verdien 3 i tabellen

Rekursiv implementasjon Merker av alle besøkte ruter i labyrint-tabellen Bunn i rekursjonen når vi kommer til nedre høyre hjørne Maks. fire rekursive kall, med flytt til hver av naborutene (høyre, ned, venstre opp) som det er lovlig å flytte til Lovlig flytt: Naboruten finnes, er fri og ikke tidligere besøkt Stopper rekursjonen med en gang en vei er funnet Merker rutene på evt. vei når rekursjonen trekker seg tilbake etter at en vei er funnet Java-kode: labyrint.java * *: Inneholder flere tips til løsningen av oblig. 2...

Oblig. 2: Springerproblemet Springer: 2 frem, 1 til siden Starter med en springer i en gitt posisjon på et n x n brett Problem: Finn en måte å flytte springeren rundt på sjakkbrettet, slik at den er innom hver rute en og bare en gang en springertur Finnes ikke alltid løsning, avhenger av startposisjon og størrelsen på brettet

Springerproblemet og backtracking Løses på en tilsvarende måte som labyrinten: Bruk en 2D-tabell til å lagre hvilke ruter som er oppsøkt Må merke en rute som ubrukt igjen når vi backtracker Prøv alle lovlige steg (maks. 8) videre fra hver posisjon Ikke gå utenfor brettet, ikke oppsøk en rute flere ganger Ta vare på antall steg og hvilke flytt som utføres Problemet er løst etter n 2 steg (alle ruter er besøkt) Bruk gjerne labyrintprogrammet som utgangspunkt

Litt kombinatorikk Kombinatorikk: Metoder og formler for å telle opp antall mulige måter som vi kan gjennomføre steg-for-steg prosesser på Eksempler: Hvor mange ulike LOTTO-rekker finnes det? Hvor mange forskjellige flush kan vi få utdelt i poker? Hvor mange ulike oppstillinger av dronninger kan vi lage på et sjakkbrett, slik at ingen står i samme rad eller kolonne? Kjennskap til grunnleggende formler fra kombinatorikken er nødvendig for å kunne forstå kompleksiteten i en del backtrackingproblemer

Multiplikasjonsprinsippet En prosess består av å gjøre n (del)valg i rekkefølge I hvert delvalg har vi ki ulike alternativer, i = 1, 2,, n Hele prosessen kan da utføres på: k 1 k 2 k 3 k n-1 k n ulike måter

Multiplikasjonsprinsippet: Et eksempel Skal velge et antrekk som består av en bukse og en genser n = 2 delvalg k1 = 3 bukser k2 = 2 gensere Totalt: k 1 k 2 = 3 2 = 6 mulige ulike antrekk

Et eksempel til: Svenske bilskilt Vanlige svenske registreringsnumre for biler består av tre bokstaver etterfulgt av tre siffer (0 9) Bokstavene I, Q, V, Å, Ä, Ö brukes ikke pga. at de ligner for mye på andre bokstaver/tall I alt 23 ulike bokstaver kan velges Det er 97 tre-bokstavskombinasjoner som ikke er tillatt å bruke

Antall forskjellige svenske bilskilt n = 6 delvalg Tre valg av bokstaver, 23 ulike muligheter i hvert valg: k 1 = k 2 = k 3 = 23 Tre valg av siffer, 10 ulike muligheter i hvert valg: k 4 = k 5 = k 6 = 10 Antall ulike skilt som inneholder ulovlige bokstavkoder: 97 10 10 10 = 97 000 Totalt antall forskjellige svenske bilskilt som kan lages: 23 23 23 10 10 10 97 000 = 12 070 000

Permutasjoner Har n objekter som alle er ulike Objektene skal stilles opp i en eller annen rekkefølge Det å bestemme en rekkefølge kan sees på som å nummerere objektene fra 1 til n En slik nummerering av n objekter kalles for en permutasjon av objektene Å endre rekkefølger kalles å permutere (eller å stokke om, bytte om) I mange backtrackingsproblemer vil løsningen være en permutasjon som oppfyller visse krav

Permutasjoner, noen eksempler Alle 6 permutasjoner av 123: 123 132 213 231 312 321 Alle 24 permutasjoner av ABCD: ABCD ABDC ACBD ACDB ADBC ADCB BACD BADC BCAD BCDA BDAC BDCA CABD CADB CBAD CBDA CDAB CDBA DABC DACB DBAC DBCA DCAB DCBA

Hvor mange permutasjoner kan lages? Kan bruke multiplikasjonsprinsippet til å regne ut antall mulige ulike permutasjoner av n objekter En permutering er en prosess med n delvalg: Velg nr. 1 : n muligheter Velg nr. 2 : n 1 muligheter Velg nr. n - 1 : 2 muligheter Velg nr. n : 1 mulighet Total antall mulige permutasjoner av n objekter: n (n - 1) (n - 2) 3 2 1 = n! (n-fakultet)

Antall permutasjoner vokser raskt 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800 11! = 39916800 12! = 479001600 13! = 6227020800 14! = 87178291200 15! = 1307674368000 16! = 20922789888000 17! = 355687428096000 18! = 6402373705728000 19! = 121645100408832000 20! = 2432902008176640000

Program for å lage og skrive ut alle permutasjoner av tallene 1, 2,, n Permutasjonene bygges opp systematisk og rekursivt, ved at vi etter tur setter alle tallene inn som nummer en, deretter som nummer to osv. Bruker en global heltallsarray p av lengde n til å lagre permutasjonene som genereres Rekursjonen følger indeksene i p Tar vare på hvilke av tallene 1, 2,.., n som allerede er brukt i en permutasjon, i en global boolsk array brukt, (initielt lik false) slik at vi ikke setter inn samme tall to ganger

public static void lagperm(int indeks) { if (indeks == n) skrivperm(); else { for (int i = 0; i < n; i++) { if (!brukt[i]) { p[indeks] = i + 1; brukt[i] = true; lagperm(indeks + 1); brukt[i] = false; } } } } Java-kode med testprogram: permutasjon.java

Dronningproblemet n dronninger skal plasseres på et n x n sjakkbrett, slik at ingen av dronningene kan slå hverandre Vi skal lage et program som finner alle slike utplasseringer av n dronninger En dronning kan beveges fra ruten den står på, i begge retninger horisontalt, vertikalt og langs de to diagonalene

To løsninger for n = 8

Antall løsninger for voksende n n 1 1 2 0 3 0 4 2 5 10 6 4 7 40 8 92 9 352 n 10 724 11 2 680 12 14 200 13 73 712 14 365 596 24 227 514 171 973 736 25 2 207 893 435 808 352 26 22 317 699 616 364 044

Dronningproblemet: n delvalg Kan betraktes som et steg-for-steg problem I hvert steg velger vi en ny posisjon på brettet og setter ut én ny dronning Tidsforbruket for en algoritme som skal løse dronningproblemet avhenger av: Størrelsen på sjakkbrettet, n Hvor tidlig vi avskjærer utbyggingen av en løsning, dvs. tar vekk sist utplasserte dronning og går tilbake (backtracker) til den forrige

Rå kraft -løsning, versjon 0.1 Prøv med alle mulige utplasseringer av n dronninger For hver mulig utplassering: Test om dette er en løsning Det kan relativt enkelt bevises at antall løsninger som må lages og testes for n = 8 er: 64 63 62 61 60 59 58 57 / 8! = 4 426 165 368 For generell n er antall løsninger som må testes: n 2 (n 2-1) (n 2-2) (n 2 - n + 2) (n 2 - n +1 ) / n! Ubrukelig for n > 7 Testprogram: bruteforce1.java

Rå kraft - løsning, versjon 0.2 Avskjæring: Ikke sett dronninger på samme rad For hver rad: Prøv alle rutene Test om hver utplassering av n dronninger er en løsning Antall løsninger som må lages og testes for n = 8 kan beregnes med multiplikasjonsprinsippet: 8 8 8 8 8 8 8 8 = 8 8 = 16 777 216 For generell n: n n Ubrukelig for n > 8 Testprogram: bruteforce2.java

Litt smartere løsning Ikke sett dronninger i samme rad eller samme kolonne En løsning blir da en permutasjon av tallene 1, 2, 3,, n Antall løsninger som må lages og testes for n = 8: 8 7 6 5 4 3 2 1 = 8! = 40 320 For generell n: n! Ubrukelig for n > 11 { 4, 7, 3, 8, 2, 5, 1, 6 } Testprogram: bruteforce3.java

Enda smartere løsning Sett ut dronningene rad for rad For hver ledige kolonne i raden: Sjekk om noen av dronningene som allerede er satt ut ovenfor kan nå dette feltet langs de to diagonalene Hvis ikke, sett ut dronning i denne kolonnen og gå videre til neste rad, ellers prøv neste ledige kolonne Hvis ingen av kolonnene kan brukes, backtrack til forrige rad og prøv en ny plassering der

Animasjon: Backtracking frem til første løsning

Implementasjon Bruker programmet for å lage permutasjoner til å bygge opp løsningene på dronningproblemet rad for rad: Permutasjonene som genereres representerer en løsning som er under utbygging Vil automatisk unngå dronninger i samme rad/kolonne Trenger bare å utvide permutasjonsprogrammet med en funksjon som sjekker de to diagonalene bakover Java-kode: dronning.java