1 Rekursion og algoritmedesign. 2 Rekursion Matematisk induktion Rekursion Simple eksempler Kryptering Plan Designmetoder Del-og-hersk Dynamisk programmering.

Slides:



Advertisements
Lignende præsentationer
Den danske befolknings syn på handicappedes rettigheder
Advertisements

Atomer Et programmeret forløb. En måde at lære på.
1 Problemkompleksitet 2 Problemers kompleksitet En ineffektiv algoritme: køretiden vokser eksponentielt med input- størrelsen Et problem, der ikke kan.
Bolig selskabernes Landsforening– Almene lejeboliger - Maj/Juni Almene lejeboliger - Danmarkspanelet - Maj/Juni 2010.
Trivselsundersøgelse og ledelsesevaluering
Algoritmer og Datastrukturer 2 Del-og-kombiner [CLRS, kapitel , , 28
1 Rekursion og algoritmedesign. 2 Rekursion Rekursiv definition af X: X defineres i termer af sig selv. Rekursion er nyttig, når en generel version af.
Symbolsk maskinsprog.
Rekursion og algoritmedesign
1 Effektiv forrentning Kjeld Tyllesen PEØ, CBS Erhvervsøkonomi / Managerial Economics Kjeld Tyllesen, PEØ, CBS.
Grundlæggende programmering Efterår 2001
GP10, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 10 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi.
Algoritmer og Datastrukturer 2 Gerth Stølting Brodal.
Økonometri 1: Specifikation og dataproblemer1 Økonometri 1 Specifikation, og dataproblemer 4. november 2005.
Representations for Path Finding in Planar Environments.
1 Nordjyllands Erhvervakademi Lektion 6 Opsamling på opgaver Mere om rekursion: –Del&Hersk –Sortering –Kompleksitet (effektivitet – ”Store O”) Abstrakte.
Kursus om borger.dk og brugen af digital signatur
FEN Diskret matematik/Seminar 3 - proofs 1 Beviser Et bevis er en argumentation, som overbeviser om, at en påstand er sand, påstanden kaldes.
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
Søgning & sortering Intro søgning Lineær søgning Binær søgning
1 Bevisteknikker. 2 Bevisteknikker (relevant både ved design og verifikation) Teorem: Der findes uendeligt mange primtal Bevis: Antag at der findes et.
1 UNION-FIND. 2 inddata: en følge af heltalspar (p, q); betydning: p er “forbundet med” q uddata: intet, hvis p og q er forbundet, ellers (p, q) Eksempel.
GP 10, 7/ Grundlæggende programmering Efterår 2001 Forelæsning 10 onsdag 7/ kl. 9:15 – 12:00.
Induktion og rekursion
FEN IntroJava AAU1 Java grundelementer Variable og datatyper Sætninger og udtryk Metoder.
FEN Rekursion og induktion1 Induktion og (især) rekursion Mange begreber defineres ud fra en basis og så en gentagen anvendelse af et antal regler.
Trivselsundersøgelse og ledelsesevaluering Anæstesiologisk Afdeling Flere ledere
1 Datalogi C Datastrukturer og algoritmer ved Keld Helsgaun.
1 Algoritmedesign. 2 Den grådige metode 3 Et problem løses ved at foretage en række beslutninger Beslutningerne træffes en ad gangen i en eller anden.
1 Sortering I elementære metoder. 2 Plan Terminologi Elementære metoder til sortering -sortering ved udvælgelse -sortering ved indsættelse -Shellsort.
Anvendelser I Leg og spil.
Matematik B 1.
Claus Brabrand, ITU, Denmark Mar 10, 2009EFFECTIVE JAVA Effective Java Presentation Workshop Claus Brabrand [ ] ( “FÅP”: First-year Project.
1 Vi ser nu på en general graf Men antager at alle afstande er heltallige (Det er ikke så restriktivt) Algoritmen leder efter den mindst mulige dækningsdistance.
Algoritmer og Datastrukturer 2 Del-og-kombiner [CLRS, kapitel 2.3, , problem 30.1.c] Gerth Stølting Brodal.
1 Algoritmik ved Keld Helsgaun. 2 Plan Algoritmebegrebet et simpelt eksempel Et eksempel på algoritmedesign.
1 Tråde 2 Plan Trådbegrebet Synkronisering Koordinering Eksempel: et flertrådet spil.
Grunde til at jeg elsker dig
GP 11, 14/ Grundlæggende programmering Efterår 2001 Forelæsning 11 onsdag 14/ kl. 9:15 – 12:00.
1 Søgetræer. 2 Binære søgetræer Definition Operationer Balancerede binære søgetræer AVL-træer Rød-sort-træer (AA-træer) B-træer Plan.
Lektion 7 Læsestof: Kopier fra Caranno
1 Design, analyse og verifikation. 2 Algoritmebegrebet Design Bevisteknikker Design ved hjælp at matematisk induktion Analyse O-notation Logaritmer Binær.
Fundamentale datastrukturer
FEN KbP/seminar 1: Specifikationer/Notationen Q 1 Kontraktbaseret programmering: Seminar 1 Om specifikationer Algoritmenotationen Q.
Design, verifikation og analyse
1 Design, analyse og verifikation. 2 Design Bevisteknikker Design ved hjælp at matematisk induktion Analyse O-notation Logaritmer Binær søgning Verifikation.
1 Sortering. 2 Plan Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion –quicksort –flettesortering.
1 Sortering. 2 Sortering ved fletning (merge-sort) 7 2 | 9 4  | 2  2 79 | 4   72  29  94  4.
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer,
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
Begreber og Redskaber 7. Plan for idag Rekursive underprogrammer Rekursive datastrukturer Rekursion vs iteration Rekursivt: Flette sortering.
1 Sortering. 2 Plan Elementære metoder til sortering -sortering ved indsættelse -Shellsort Sorteringsmetoder baseret på rekursion –quicksort –flettesortering.
KF04 GRAY Item 2, 12, 22, 32, 42, 52. Consider a builder when faced with many constructor parameters Item 2.
Anvendelser I Leg og spil.
Længste plateau En klassisk problemstilling (Gries, 1981) - og her i Java!!! Denne opgave drejer sig om at bestemme længden af det længste plateau i en.
Grundlæggende programmering Forår 2002
Algoritmer og Datastrukturer 2 Del-og-kombiner [CLRS, kapitel , , 28
Begreber og Redskaber 11. Plan for idag Lidt afrunding: Collections Framework i Java Noget om oversættere og sprog Evaluering Sidste gang øvelser før.
Deadlock Definition deadlock (baglås) er en tilstand som en mængde af processer kan være i en mængde processer er i deadlock hvis alle processerne står.
Begreber og Redskaber 4. Plan for idag Om metoder, parametre, returværdier Et par ord om objekt-orientering Håndkøring af programmer.
Algoritmer og Datastrukturer 2 Gerth Stølting Brodal.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering6A.1 Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Trinvis forfinelse Systematisk, gradvis udvikling af programmer.
Programmering med interfaces Separering af specifikation, anvendelse og implementation.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
I o p o DAIMI, AU, November 1999Introducerende objektorienteret programmering9D.1 Del, løs og kombinér.
Algoritmer og Datastrukturer 2
Algoritmer og Datastrukturer 2
Præsentationens transcript:

1 Rekursion og algoritmedesign

2 Rekursion Matematisk induktion Rekursion Simple eksempler Kryptering Plan Designmetoder Del-og-hersk Dynamisk programmering Baksporing

3 Tre vigtige begreber Syntaks (notation) Semantik (betydning) Pragmatik (anvendelse)

4 Metoder til algoritmedesign Algoritmedesign er en kreativ proces. Der findes ingen generel mekanisk metode (algoritme) til design af en algoritme for et forelagt problem. Derimod findes en række metoder, eller rettere “regler for tænkning”, som ofte fører til korrekte og effektive algoritmer. Nogle af disse metoder er baseret på matematisk bevisførelse. Dermed “indbygges” korrekthed i algoritmerne. Andre har mere karakter af gode råd.

5 Matematisk induktion uformel beskrivelse Hvis (1) jeg kender den forreste person, og (2) hvis jeg for enhver person, jeg kender i køen, også kender dennes efterfølger, så kender jeg alle personer i køen. Også selv om køen er uendelig lang. Nogle personer står i en kø:

6 Lad T være et teorem, der skal bevises, og lad T være udtrykt i termer af heltalsparameteren n. Teoremet T gælder da for enhver værdi af n ≥ c, hvor c er en konstant, hvis følgende to betingelser er opfyldt: 1. Basistilfældet: T gælder for n = c, og 2. Induktionsskridtet: Hvis T gælder for n-1, så gælder T for n. Matematisk induktion formel beskrivelse Antagelsen i induktionsskridtet kaldes induktionshypotesen.

7 Eksempel: Sortering af n tal i stigende rækkefølge Antag at vi kan sortere n-1 tal. Vi kan da opnå en sortering af n tal ved først at sortere n-1 af tallene, og derefter indsætte det n´te tal på den rette plads (sortering ved indsættelse), eller bestemme det mindste af de n tal og sætte det forrest, sortere de resterende n-1 tal, og derefter sætte dem bagefter dette forreste tal (sortering ved udvælgelse).

8 Eksempel Binær søgning For at finde et element i et sorteret array med n elementer: Opdel arrayet i to (næsten) lige store dele. Afgør i hvilken af de to dele, elementet skal findes. Søg videre på samme måde (rekursivt) i denne del. int binarySearch(Comparable[] a, Comparable key, int low, int high) { if (low > high) return NOT_FOUND; int mid = (low + high) / 2; if (a[mid].compareTo(key) < 0) return binarySearch(a, key, mid + 1, high); if (a[mid].compareTo(key) > 0) return binarySearch(a, key, low, mid - 1); return mid; }

9 Benyt en driver-rutine til at forenkle brug private int binarySearch(Comparable[] a, Comparable key, int low, int high) {... } public int binarySearch(Comparable[] a, Comparable key) { return binarySearch(a, key, 0, a.length - 1); }

10 Del-og-hersk er en vigtig teknik til algoritmisering. Teknikken er et eksempel på brugen af stærk induktion. Del-og-hersk (1) Del problemet op i mindre delproblemer. (2) Hersk ved at løse hvert delproblem. (3) Kombiner resultaterne til en løsning for det oprindelige problem. Hvis delproblemerne er mindre udgaver af det oprindelige problem, kan rekursion ofte benyttes med fordel.

11 Del-og-hersk ved rekursion Pseudokode: solve(Problem p) { if (size(p) <= critical_size) solve_small_problem(p); else { subproblem = divide(p); solve(subproblem[0]); solve(subproblem[1]);.... combine_solutions(); }

12 Problem. Beregn power(x,n) = x n, hvor x er et reelt tal, og n er et positivt heltal. Simpel løsning: power = x; for (i = 1; i < n; i++) power *= x; Antal multiplikationer: n-1. Eksempel: Potensopløftning

13 double power(double x, int n) { if (n == 1) return x; if (n % 2 == 0) { double p = power(x, n/2); return p * p; } return x * power(x, n-1); } Det kan bevises, at antallet af multiplikationer er cirka log 2 n. (Hvis n fordobles, øges antallet af multiplikationer kun med 1). Anvendelse: kryptologi, hvor x og n er meget store heltal. Løsning ved del-og-hersk: Hvis n er lige, opløses problemet power(x,n) i to (ens) delproblemer, power(x,n/2) og power(x,n/2), og løsningen bestemmes som power(x,n/2)*power(x,n/2). Ellers (hvis n er ulige) bestemmes løsningen som x*power(x,n-1).

14 Eksempel: Beregning af den maksimale delsekvenssum Problem. Givet en sekvens (a 1,a 2,.., a n ) af reelle tal. Find en delsekvens (a i,a i+1,.., a j ) af konsekutive elementer, sådan at summen af dens elementer er størst mulig. Enten findes den maksimale delsekvens (2) helt i den højre del, eller (3) i en sekvens, der indeholder midterelementet Opdel problemet i to omtrent lige store dele: (1) helt i den venstre del,

15 De to første værdier bestemmes ved rekursion. Den sidste værdi bestemmes som summen af det maksimale suffix for sekvensen til venstre for midterelementet (inklusiv dette), og det maksimale prefix for sekvensen til højre for midterelementet. Den maskimale delsekvenssum bestemmes som maksimum af disse 3 værdier. 3 delproblemer

16 int maxSum(int[] a, int left, int right) { if (left == right) return a[left] > 0 ? a[left] : 0; int mid = (left + right) / 2; return max3(maxSum(a, left, mid - 1), maxSum(a, mid + 1, right), maxSuffix(a, left, mid) + maxPrefix(a, mid + 1, right)); } Javakode int maxSuffix(int[] a, int left, int right) { int sum = 0, maxSum = 0; for (int i = right; i >= left; i--) if ((sum += a[i]) > maxSum) maxSum = sum; return maxSum; } maxPrefix implementeres analogt

17 Kompleksitet Tiden, det tager at løse et problem med n tal, T(n), hvor n er en potens af 2, opfylder rekursionsligningerne T(n) = 2*T(n/2) + O(n) T(1) = O(1) Hvis O(n) og O(1) erstattes med henholdsvis n og 1, bliver løsningen T(n) = n log n + n Der gælder således, at T(n) = O(n log n).

18 Rekursion Rekursiv definition af X: X defineres i termer af sig selv. Rekursion er nyttig, når en generel version af X kan defineres i termer af simplere versioner af X. Et problem løses rekursivt ved (1) at nedbryde det i mindre delproblemer af samme slags, (2)fortsætte med dette indtil delproblemerne er så simple, at de umiddelbart kan løses, og (3)kombinere løsningerne af delproblemerne til en løsning af det oprindelige problem.

19 for at opnå simple og præcise definitioner elegante løsninger på problemer, der ellers er svære at løse algoritmer, der er simple at analysere Tænk rekursivt

20 int factorial(int n) { if (n == 1) return 1; return n * factorial(n-1); } Upræcis definition: n! = n * (n-1) * (n-2) *... * 2 * 1 Simpelhed og præcision (eksempel: Fakultetsfunktionen) Præcis (rekursiv) definition: 1, hvis n = 1 n * (n-1)!, hvis n > 1 n! = {

21 Implementering af rekursion En rekursiv metode kalder en kopi (inkarnation) af sig selv. Kun én inkarnation er aktiv ad gangen. Resten venter (på, at den kopi, de har kaldt, returnerer). Rekursion kan implementeres ved hjælp af en stak (idet inkarnationerne returnerer i omvendt rækkefølge i forhold til den rækkefølge, hvori de er kaldt).

22 int f(int n) { if (n == 1) return 1; return n * f(n-1); } Illustration af kaldet f(4) n = 4 f = ? f(4) n = 4 f = ? f(4) f(3) n = 3 f = ? n = 4 f = ? f(4) f(3) n = 3 f = ? f(2) n = 2 f = ? n = 4 f = ? f(4) f(3) n = 3 f = ? f(2) n = 2 f = 2 n = 4 f = ? f(4) f(3) n = 3 f = 6 n = 4 f = 24 f(4) f(3) f(2) f(1) n = 4 f = ? n = 3 f = ? n = 2 f = ? n = 1 f = 1

23 Brug af stak til håndtering af metodekald int f(int a1, int a2, int a3) { int b1, b2, b3; }

24 At flytte n skiver fra pinden from til pinden to kan foretages ved først at flytte de øverste n-1 skiver fra pinden from til pinden via. Dernæst flyttes den nederste skive fra pinden from til pinden to. Endelig flyttes de n-1 skiver fra pinden via til pinden to. Tårnene i Hanoi (fra et munkekloster i Tibet) Problem. Flyt skiverne fra pinden from til pinden to, idet en større skive aldrig må placeres oven på en mindre skive. fromviato

25 void move(int n, int from, int to, int via) { if (n == 0) return; move(n-1, from, via, to); System.out.println("Move " + from + " to " + to); move(n-1, via, to, from); } move(2,2,3,1) move(2,1,2,3) move(1,1,3,2) move(0,1,2,3) move(0,3,2,1) move(1,2,1,3) move(0,2,3,1) move(0,1,2,3) move(3,1,3,2) Kaldtræ for move(3,1,3,2) move(0,1,2,3) move(0,3,2,1) move(1,1,3,2) move(0,2,3,1) move(0,3,1,2) move(1,3,2,1)

26 Effektivitetsanalyse Tidsforbruget er proportionalt med antallet af flytninger, F(n), hvor n angiver antallet af skiver. F(n) = F(n-1) F(n-1) = 2*F(n-1) + 1, for n > 1 F(1) = 1 som har løsningen 2 n - 1. Pladsforbruget er det maksimale antal uafsluttede kald af move, dvs. n. Samlet tidsforbrug for 64 skiver, hvis hver flytning tager 1 sekund: 2 64 sekunder ≈ sekunder ≈ år

27 Fundamentale regler for rekursion Basistilfælde: Hav altid mindst et tilfælde, der kan løses uden brug af rekursion. Gør fremskridt: Ethvert rekursivt kald bør nærme sig et basistilfælde. Tro på det: Antag altid, at et rekursivt kald virker som ønsket. Undgå dobbeltarbejde: Sørg for at hvert delproblem kun løses én gang. Benyt aldrig rekursion som en erstatning for en simpel løkke.

28 Eksempel (tegnvis udskrivning af et positivt heltal) void printDecimal(int n) { if (n >= 10) printDecimal(n/10); System.out.print((char) '0' + (n % 10)); } Udskriv n = 7913

29 Eksempel (tegning af en lineal) void drawRuler(Graphics g, int left, int right, int level) { if (level < 1) return; int mid = (left + right) / 2; g.drawLine(mid, 80, mid, 80 - level * 5); drawRuler(g, left, mid - 1, level- 1 ); drawRuler(g, mid + 1, right, level - 1 ); } Kald: drawRuler(g, 10, , 8);

30 Rekursion har omkostninger i tid og plads. Omkostningen i tid skyldes mekanismer for metodekald og parameter- overførsel. Omkostningen i plads er bestemt af det maksimale rekursionsniveau (det maksimale antal metodeaktiveringer, der eksisterer samtidigt). Enhver rekursiv algoritme kan mekanisk transformeres til en ikke-rekursiv algoritme Fjernelse af rekursion (et eksempel på algoritmetransformation) (ved brug af eksplicit stak)

31 Hvis “indstikket” sker helt til slut i enhver operation, må dette være det samme som iteration. Rekursion Iteration void p(type x) { if (b(x)) S1; else { S2; p(f(x)); } Kald : p(a) Fjernelse af halerekursion Iteration er at sætte operationer af samme art efter hinanden. Rekursion er at stikke operationer af samme art ind i hinanden. type x = a; while (!b(x)) { S2; x = f(x); } S1;

32 RSA-kryptering (Rivest, Shamir og Adleman, 1978) Problem: Alice ønsker at sende en besked til Bob, men således at ingen andre kan læse hendes besked. Løsning: Bob offentliggør to tal, e og N, som alle, der sender beskeder til ham, skal benytte. Kryptering: Alice sender sin besked M i form af tallet R = M e (mod N). Dekryptering:Den oprindelige besked gendannes af Bob ved hjælp af transformationen R d (mod N), hvor d er et tal, som kun Bob kender.

33 RSA-kryptering Bestemmelse af e, d og N: 1) Vælg to store primtal p og q (typisk på mere end 100 cifre). 2) Beregn N = p*q. 3) Beregn N’ = (p-1)*(q-1). 4) Vælg e > 1, således at gcd(N’, e) = 1. 5) Vælg d, således at e*d (mod N’) = 1. [ d.v.s., således at d er multiplikativ invers til e ]. Så vil (M e ) d = M (mod N). Bob bør hemmeligholde p, q, N’ og d.

34 Et eksempel (1) p = 47 og q = 79 (to primtal) (2) N = p*q = 3713 (3) N’ = (p-1)*(q-1) = 3588 (4) e = 37 (gcd(N’, e) = 1) (5) d = 97 (e*d (mod N’) = 1, idet e*d = 3589)

35 Eksempel fortsat (e = 37, d = 97, N = 3713) Meddelelse: ATTACK AT DAWN Kodning: A = 01, B = 02, C = 03, o.s.v. A T T A C K A T D A W N (opdel i blokke á 2 tegn) Kryptering ved den offentlige nøgle 37: = = 2392 (mod 3713) Dekryptering ved den hemmelige nøgle 97: = = 2001 (mod 3713)

36 Delalgoritmer (1)Potensopløftning af lange heltal (M e og R d ). (2)Afgørelse af om et langt heltal er et primtal. (3)Multiplikation af to lange heltal ((p-1)*(q-1)). (4)Bestemmelse af største fælles divisor for to lange heltal (gcd(N’, e)). (5)Bestemmelse af det multiplikative inverse tal til et langt heltal(e*d (mod N’) = 1).

37 Sikkerhed ved RSA-kryptering Hvis d kan bestemmes ud fra kendskab til e og N, brydes brev- hemmeligheden. Hvis N kan faktoriseres, N = p * q, så kan d bestemmes. Imidlertid er faktorisering af et tal en meget vanskelig opgave. Med dagens teknologi vil det tage millioner af år for en computer at faktorisere et tal bestående af 200 cifre.

38 Del-og-hersk (top-til-bund, top-down): For at løse et stort problem deles problemet op i mindre delproblemer, der løses uafhængigt af hinanden. Dynamisk programmering Dynamisk programmering (bund-til-top, bottom-up): For at løse et stort problem løses alle mindre delproblemer, og deres løsninger gemmes og benyttes til at løse større problemer. Således fortsættes, indtil problemet er løst. Betegnelsen stammer fra operationsanalysen, hvor “programmering” benyttes om formulering af et problem, således at en bestemt metode kan anvendes.

39 Dynamisk programmering Moderne definition: Bund-til-top implementering af rekursive programmer med overlappende delproblemer. Top-til-bund implementering er dog også mulig. Dynamisk programmering er baseret på følgende simple princip: Undgå at gentage en beregning.

40 F(n) = F(n-1) + F(n-2) for n >= 2, F(0) = 0, F(1) = Simpelt eksempel Beregning af Fibonacci-tal (Fibonacci, 1202) Talrækken vokser eksponentielt: F(n)/F(n-1) går imod (det gyldne snit = (1+ )/2) 5

41 int F(int n) { return n <= 1 ? n : F(n-1) + F(n-2); } Rekursiv metode til beregning af F(n) Ineffektiviteten skyldes, at de samme delproblemer løses mange gange. F.eks. F(9) = F(8) + F(7) = F(7) + F(6) + F(7) = F(6) + F(5) + F(6) + F(6) + F(5) Simpel, men meget ineffektiv. Antallet af kald, C(n), tilfredsstiller rekursionligningerne C(n) = C(n-1) + C(n-2) + 1, C(1) = C(0) = 1 som har løsningen C(n) = F(n+2) + F(n-1) - 1. C(n) er altså større end det Fibonacci-tal, der skal beregnes!

42 Vedligehold en tabel (indiceret ved parameterværdien) indeholdende * 0, hvis den rekursive metode endnu ikke er kaldt med denne parameterværdi * ellers det resultat, der skal returneres Første kald af metoden for en given parameterværdi:beregn som før, men gem desuden resultatet. Efterfølgende kald med samme parameterværdi:returner resultatet fra det første kald. Undgå genberegninger (benyt “caching”) int F(int n) { if (Fknown[n] != 0) return Fknown[n]; int r = n <= 1 ? n : F(n-1) + F(n-2); Fknown[n] = r; return r; }

43 Effektivitet Køretid: lineær Husk kendte resultater: 1 0 Simpel rekursiv metode: F(9) Køretid: eksponentiel

44 Eksempel: Dynamisk programmering til beregning af Fibonacci-tal: F[0] = 0; F[1] = 1; for (i = 2; i <= n; i++) F[i] = F[i-1] + F[i-2]; Tidsforbruget er lineært. Dynamisk programmering (traditionel): * Tabellæg løsningerne til delproblemerne * Opbyg tabellen i stigende orden af problemstørrelse * Benyt gemte løsninger til at bestemme nye løsninger Bund-til-top-tilgang

45 Afskaffelse af tabel Faktisk kan F(n) beregnes i logaritmisk tid: F = 1; Fprev = 0; for (i = 2; i <= n; i++) { F += Fprev; Fprev = F - Fprev; }

46 Optimal møntveksling Udbetal et beløb i mønter, således at antallet af mønter er minimalt. Eksempel: Hvis beløbet skal udbetales i amerikanske cents, kan mønterne 1-, 5-, 10- og 25-cent benyttes. Veksling af 63 cents kan da foretages med 6 mønter, nemlig to 25- cent, en 10-cent og tre 1-cent. For disse mønter vil en grådig algoritme altid give en optimal løsning. Men hvis der f.eks. indføres en 21-cent-mønt, virker denne metode ikke.

47 Rekursiv top-til-bund-løsning int[] coins = {1, 5, 10, 21, 25}; int makeChange(int change) { if (change == 0) return 0; int min = Integer.MAX_VALUE; for (int i = 0; i < coins.length; i++) if (change >= coins[i]) min = Math.min(min, 1 + makeChange(change - coins[i])); return min; } Benyt ikke denne algoritme! Eksponentielt tidsforbrug. Undgå genberegninger. Beregn for hver mønt det minimale antal mønter, der kan benyttes til at veksle det resterende beløb. Tag minimum.

48 int makeChange(int change) { if (change <= 0) return 0; if (minKnown[change] > 0) return minKnown[change]; int min = Integer.MAX_VALUE; for (int i = 0; i < coins.length; i++) if (change >= coins[i]) min = Math.min(min, 1 + makeChange(change - coins[i])); minKnown[change] = min; return min; } Brug af kendte løsninger

49 Udskrivning af mønterne i en optimal veksling while (change > 0) { System.out.println(lastCoin[change]); change -= lastCoin[change]; } Gem i en tabel, lastCoin, for ethvert beløb den sidst valgte mønt i en optimal veksling af beløbet.

50 int makeChange(int change) { if (change <= 0) return 0; if (minKnown[change] > 0) return minKnown[change]; int min = Integer.MAX_VALUE, minCoin = 0; for (int i = 0; i < coins.length; i++) if (change >= coins[i]) { int m = 1 + makeChange(change - coins[i]); if (m < min) { min = m; minCoin = coins[i]; } } lastCoin[change] = minCoin; minKnown[change] = min; return min; }

51 int makeChange(int change) { minKnown[0] = 0; for (int c = 1; c <= change; c++) { int min = Integer.MAX_VALUE; for (int i = 0; i < coins.length; i++) if (c >= coins[i]) min = Math.min(min, 1 + minKnown[change - coins[i]]); minKnown[c] = min; } return minKnown[change]; } Bund-til-top-løsning (uden rekursion) Brug fundne løsninger til at bestemme den næste løsning. Køretiden er proportional med change*coins.length.

52 Baksporing (engelsk: backtracking) Benyt rekursion til at prøve alle muligheder.

53 Søgning i en labyrint WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW WWW ******W W W W W W W W W W WWWWW*W W W W W W W W WWWWWWWWWW W***** WW W WWWW WWW W WWWWWW W W W W*WWWWWWWW W W W W**** W********W WWWWWW W* W W W W**W*W**WWWWW** W W*WWWWWWWWWWWW WW WW*W*W*WWWW*** W WWWW W W********************W*W*W *WWWW W W WWWWWWWWWWWWWWWWWWWW W***W W****W W WW W W W WWWWWWWWWWW*WWWWWWWW W WWWWWWWWWW WWWW WWWWW W W*W***WW W W W W W ***W***** WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW WWW Løsning Slut Start Slut Problem WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW W W W W W W W W W W WWWWW W W W W W W W W WWWWWWWWWW W WW W WWWW WWW W WWWWWW W W W W W W W W W W WWWWW W W WWWWWWWWWWWW WW WW W W WWWW W WWWW W W W W W WWWW W W WWWWWWWWWWWWWWWWWWWW W W W W W WW W W W WWWWWWWWWWW WWWWWWWW W WWWWWWWWWW WWWW WWWWW W W W WW W W W W W W WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

54 public class Program { static String[] problem = { "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW", " W W W W W W W W W W", "WWWWW W W W W W W W W WWWWWWWWWW", "W WW W WWWW WWW W WWWWWW W W W", "W W W W W W W WWWWW W", "W WWWWWWWWWWWW WW WW W W WWWW W WWWW W", "W W W W WWWW W W", "WWWWWWWWWWWWWWWWWWWW W W W W W WW W", "W W WWWWWWWWWWW WWWWWWWW", "W WWWWWWWWWW WWWW WWWWW W W W WW W", "W W W W W ", "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" }; static int xStart = 1, yStart = 0, xEnd = 11, yEnd = 40; static boolean solutionFound = false; static StringBuffer[] solution = new StringBuffer[problem.length];

55 public static void main(String[] args) { for (int x = 0; x < problem.length; x++) solution[x] = new StringBuffer(problem[x]); visit(xStart, yStart); if (solutionFound) for (int x = 0; x < solution.length; x++) System.out.println(solution[x]); }

56 static void visit(int x, int y) { solution[x].setCharAt(y, '*'); solutionFound = (x == xEnd && y == yEnd); for (int d = 1; d <= 4 && !solutionFound; d++) { int xNext, yNext; switch(d) { case 1: xNext = x; yNext = y - 1; break; case 2: xNext = x - 1; yNext = y; break; case 3: xNext = x; yNext = y + 1; break; case 4: xNext = x + 1; yNext = y; break; } if (xNext >= 0 && xNext = 0 && yNext < solution[xNext].length && solution[xNext].charAt(yNext) == ' ') visit(xNext, yNext);} if (!solutionFound) solution[x].setCharAt(y, ' '); }

57 Læs kapitel 8 og 9 Afsnit 9.3 og 9.6 kan læses kursorisk. Beviser kan overspringes. Løs følgende opgaver Opgave 16: 7.19 (1 point) Opgave 17: 7.20 (2 point) Opgave 18: 7.25 (3 point, ikke-obligatorisk) Opgave 19: Se næste side (4 point, ikke-obligatorisk) Afleveringsfrist: tirsdag den 30. oktober Ugeseddel oktober oktober

58