Doina Logofătu
Grundlegende
Algorithmen mit Java
Aus dem Bereich IT erfolgreich lernen
Algorithmen und Problemlösungen mit C++
von Doina Logofătu
Programmieren lernen mit Java
von Erwin Merker und Roman Merker
Grundkurs Java-Technologien
von Erwin Merker und Dietmar Abts
Java ist eine Sprache
von Ulrich Grude
Grundkurs Java
von Dietmar Abts
Masterkurs Client-/Server-Programmierung mit Java
von Dietmar Abts
Grundlegende Algorithmen mit Java
von Doina Logofătu
www.vieweg.de
Doina Logofătu
Grundlegende
Algorithmen mit Java
Vom Algorithmus zum fertigen Programm –
Lern- und Arbeitsbuch für Informatiker
und Mathematiker
Mit 115 Abbildungen
Bibliografische Information Der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie;
detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de> abrufbar.
Das in diesem Werk enthaltene Programm-Material ist mit keiner Verpflichtung oder Garantie irgendeiner Art verbunden. Der Autor übernimmt infolgedessen keine Verantwortung und wird keine daraus
folgende oder sonstige Haftung übernehmen, die auf irgendeine Art aus der Benutzung dieses
Programm-Materials oder Teilen davon entsteht.
Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk
berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im
Sinne von Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher
von jedermann benutzt werden dürfen.
Höchste inhaltliche und technische Qualität unserer Produkte ist unser Ziel. Bei der Produktion und
Auslieferung unserer Bücher wollen wir die Umwelt schonen: Dieses Buch ist auf säurefreiem und
chlorfrei gebleichtem Papier gedruckt. Die Einschweißfolie besteht aus Polyäthylen und damit aus
organischen Grundstoffen, die weder bei der Herstellung noch bei der Verbrennung Schadstoffe
freisetzen.
1. Auflage 2008
Alle Rechte vorbehalten
© Friedr. Vieweg & Sohn Verlag | GWV Fachverlage GmbH, Wiesbaden 2008
Lektorat: Günter Schulz / Andrea Broßler
Der Vieweg-Verlag ist ein Unternehmen von Springer Science+Business Media.
www.vieweg.de
Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Jede
Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist
ohne Zustimmung des Verlags unzulässig und strafbar. Das gilt insbesondere
für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.
Umschlaggestaltung: Ulrike Weigel, www.CorporateDesignGroup.de
Druck und buchbinderische Verarbeitung: MercedesDruck, Berlin
Gedruckt auf säurefreiem und chlorfrei gebleichtem Papier.
Printed in Germany
ISBN 978-3-8348-0369-6
ȱ
ȱȱ
ȱ¢ȱȱȱ¢ȱ ȱȱȱ ȱǵȱȱ
ȱȱDZȱȱȱȱȱǯȱȱ
ȱ ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
Geleitwort
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ ȱȱǮ ȱȱ ȱ ȃȱ ȱ ȱ
£ȱ ȱ ȱ £ȱ ¡§ȱ ȱ ȱ ȱ ȱ ãȬ
£ȱ ǻ£ǯȱ ǯȱ Ǯȱ ȱ Ȉǰȱ Ǯ¢ȱ ȈǼǯȱ ȱ
§ȱ ȱ Ȯȱ Ǯȱ Ȉȱ ȱ ûȱ Ȭ
ǰȱȱǮȱȱȈȱȱȱûȱȱȬ§ȱȱȱ
ȱȱ£ȱȱȱȱȱ ȱȬ
ûȱȱȱ ȱǯȱ
ȱ
ȱ ã£ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ Ȭȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ Ȭ
ȱȬȱ§ǰȱȱȱȱtȱȱ ȱãȬ
ǯȱ ȱȱȱ ȱȱȱ ȱȱȱ£ȱȱ¢ȱ
ȱ£ǯȱ
ȱ
ȱȱ§ȱȱȱȱȱ ǰȱȱȱ ȱ
£ȱ ǰȱȱȱ Ȭǯȱȱȱ£ȱȱ Ȭ
ȱȱ ȱ ǰȱ ȱȱ £ȱȱ ȱȱ ȱ ȱûȬ
ȱȱȱȱȱ ȱ ǯȱȱûȱ£Ȭ
ȱȱȱȱȱȱ ȱȱ§Ȭ
ȱȱȱ£ȱ£ȱǻȱûȱȱ¢ǼǰȱȬ
§ȱ ȱ £ ȱ ȱ ȱ ǯȱ ûȱ ȱ ȱ ȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ śǰȱ ȱ ȱ ȱ Ŝȱ ûȱ ȱ
ǰȱȱȱȱȱ ȱȱȱǰȱ£ǯȱǯȱȱȬ ȱ
ȱȱȱǯȱȱǯǯ¢ǯȱȱȱȱȱȱȬ
ȱȱȱȱǻȱȱȱǼȱȱȱȱȱȱȱȬ
ȱDzȱȱ ȱȈȈȱȱȱȱȱȱȬ
ȱȱǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ
ǰȱ ȱ ¡ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ
ȱ £ǯȱ
ȱ
ǯȱȱûȱ
VII
Vorwort
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱ ȱȱ ȱȱ ȱȱ ȱ
ȱãȱȱƸƸȱǰȱȱȱ£ȱ ȱȱǯȱȱȱ
ȱ ȱ ȱ ȱ ãđȱ ȱ ǰȱ §ȱ ȱ ȱ
ûȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
£ǯȱȱȱȱȱȱȱȱ ȱûȱȱȱȱ Ȭ
¡§ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
§ȱ ȱ ¢ȱ ȱ ȱ ȱ §£ȱ ãȱ ǯȱ
£ȱ ȱ ȱ ȱ ȱ ȱ £ǯȱ ǯȱ ȱ Ȭȱ ȱ
¢Ȭ ǰȱȱȱȬ ȱȱȱǻȱȱǼȱȱ
ȱ ûȱ ȱ ¢ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
§ȱȱȱƸƸȬȱûȱȱȱđȱȱȱ£§£ȱ
tȱ ǯȱ ȱ ȱ ȱ ȱ ãȱ ȱ £ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ
ȱ§ȱǰȱûȱȱȱȱãȱ£ȱǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ŜŖȱ ȱ £ ǯȱ
ǰȱ ȱ §ȱ ¢ȱ ȱ ȱ ȱ ãȱ ǰȱ ȱ ŘŚŖȱ tȬ
ȱȱȱŗřŖȱȱȱǯȱȱãȱ ȱ ȱȱ
ȱ ȱ ãȱ ȱ ȱ tȱ ûȱ ȱ ǯ ȱ Ȭ
ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ûȱ ǯȱ ȱ ãȱ ȱ ȱ Ȭ
ȱûûǯȱȱȱȱȱ¢ȱȱ ȱȱãǰȱ
ȱȱȱȦȱã£ȱȱȱ Ȭ
ȱ §ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ û ãȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ §ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱȱȱȱȱǰȱȱȱȱȱ §ǯȱ
ȱȱȱ ȱȱ ȱŗǯŜǯȱȱ ǰȱȱĸȱȱ£ȱ
ûȱ ȱ ǻDZȦȦǯǯȦȦ Ǽǯȱ ȱ ȱ ȱ ãȱ
tǰȱȱȱȱǰȱȱ£ȱ§ȱȱȱȱ£ȱ
ǰȱȱȱȱȱȱȱ ȱãȱȱȱȬ
§ȱǯȱȱ
IX
ȱ
ȱȱ£ ǯȱȱ ȱȱȱ ȱ ȱȱ
ȱ £ȱ £ ǯȱȱȱ ȱȱ ȱǯȱȱ
ǰȱȱȱǰȱȱǰȱȱȱȱȱȱǰȱȱȱ
ȱȱûǰȱ ȱȱȱȱ¡ǰȱȱȱȱǰȱ£ȱ ǯȱȱ
ȱ ȱ ǰȱ ȱ £ǯȱ ǯȱ Ȭǰȱ Ȃȱ ǰȱ
ûȱ ȱ ǰȱ Ȭǰȱ ȱ ȱ ǰȱ §ǰȱ ¡ȱ ûǰȱ
ȱ ȱ £ȱ ȱ Ȭ£ǯȱ ȱ ȱ ȱ Ȭ
ȱȱȱȱ¢ȱǻǼǰȱ ȱ¢ȱ
ȱ ȱ ǻ Ǽȱ ȱ Ȭȱ ¢ȱ ȱ ȱ ǻ Ǽȱ ȱ
ȱ£ǰȱ£ȱȱûȱȱȱ£ȱǯȱ
ȱ
ȱ ȱ £ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ ȱ đǰȱ £ ȱ £ ȱ ȱ
tȱ DZȱȱ ȱ ûǰȱ §ȱ ȱ ȱ ǰȱ ȱ
ȱǰȱȱȱǰȱãȱȱ¢ǯȱ
ȱ
ȱȬȱ£ȱȱȱȱDZȱ
ȱ
ǯȬȬǯȱ
ȱ
ȱ ȱ ǰȱ ȱ ȱ ǰȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ Ȭ
DZȱȱ
ȓ¢ǯȱ
ȱ
ûȱȱȱȱȱǯȱ
ȱ
ȱ
ȱ
ȱûȱȱȱȱȱǷȱ
ȱ
ȱ
ȱ
ûǰȱȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ ©ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱŘŖŖŝȱ
ǯȬǯȱ
X
Danksagung
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
£ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ûǰȱ ȱ ȱ ȱ
ȱȱ£ ȱȱ ȱȱ£ȱȱǯȱûȱȱȱȱ
ȱãȱ ǰȱ ȱ§ȱȱ ȱȱȱȱȱ
ȱ ûȱ ȱ ȱ ȱ ȱ Ȭ ȱ ǯȱ ǯȱ
ȱ ûȱ ȱ £ ȱ ŗşŞŜȱ ȱ ŗşŞŞȱ ȱ ȱ £ ȱ ȱ ǻȬ
Ǽȱȱȱ ȱȬ¢ȱǻ Ǽȱȱ ȱȱȱ
ȱȱȱȱȱȱȱȱȱû ȱ
ǯȱ
ȱ
ȱȱȱȱ£ȱȱ£ȱȱ ǰȱȱȱȱ
ȱȱȱȱ Ȭȱȱȱȱȱȱȱȱǯȱ
ȱ
ȱ ȱ ȱ ûȱ ȱ ǯȱ ǯȱ ȱ ǰȱ ȱ ȱ ȱ
ȱȱȱ§ȱǯȱȱȱȱȱǰȱ
ȱȱȱȱȱȱȱ£ȱ £ȱȱȱȱǮȱȱ
ȱ Ȅȱ £ȱ ǯȱ đȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
ȱǻȱŗŘǰȱ ȱŝǰȱǼȱȱȱȱȱ
ȱ ǻ ȱ ŚǼȱ ǯȱ tȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ã ȱ ¢ǰȱ ȱ đǰȱ ǯȱ ûȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ §ȱûǯȱûȱȱȱǯȱȱ
ȱ
ûȱ ȱ£ȱȱȱȱȱȱ ȱǯȱǯȱȱȱ
ȱǻ§ȱǰȱǼǰȱǯȱǯȱȱ ȱȱǯȱǯȱȱ
l©óȱǻȱ§ȱǰȱ§Ǽǯȱ
ȱ
ûȱ ȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ ûǰȱ ȱ ȱ ȱ ȱ ȱ
ȱǯȱǯȱȱ ȱȱǻȱ Ǽǰȱ ȱ ǯȱȱǻȱȱ
ǰȱ ȱ ȱ Ǽǰȱ ȱ ǯȱ ȱ ǻȱ ȱ ȱ Ǽȱ ȱ Ȭ
ȱȱǻȱȱȱȬ Ǽǯȱ
XI
ȱȱ ȱȬȱǻ Ǽȱûǰȱȱȱȱȱȱȱ ȱ
ȱ ȱ ȱ ȱ ȱ û£ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǯȱ
ȱȱ
ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ǻ ¢ȱ
Ǯ ǯȱ ȄǼȱȱȱȱǻȱŝǼȱȱȱȱ ȱȱ
ȱȱ§ǯȱȱȱȱȱȱȱȱȱ
ȱǰȱȱȱ ȱûȱȱȱ£ȱǯȱ
ȱȱ
ȱđȱȱȱǰȱȱȱȱȱȱãȱǯȱ
ȱ
ȱ
ȱ
ȱ
ûǰȱȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ ©ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱŘŖŖŝȱ
XII
Inhaltsverzeichnis
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
GELEITWORT von Dr. Eric Müller
VII
VORWORT
IX
DANKSAGUNG
XI
ȱ
ȱ
1 ALGORITHMEN – GRUNDLEGENDE KONZEPTE
1
Abstammung des Wortes Algorithmus
Alternative Definitionen
Beispiele für Algorithmen
Euklidischer Algorithmus
Das Sieb des Eratosthenes
Binäre Suche
Rezept für Tiramisu
Vom Problem zur Lösung
Eigenschaften eines Algorithmus
Algorithmik
Das RAM-Rechnermodell
Die Komplexität von Algorithmen
Optimalität, Reduktion, Beispiele
Wachstum von O(g(n))
Die reelle Zeit eines Algorithmus (polynomial vs. exponentiell)
Klassifizierung der Probleme (P, NP, NP-vollständig, NP-hart)
Probleme NP-vollständig (NP-complete)
Das Erfüllbarkeitsproblem (SAT)
Die Klasse der NP-hart Probleme
Aufgaben
1
1
2
2
3
4
6
7
10
10
11
12
14
17
17
18
19
20
21
22
ȱ
XIII
2 VERSCHACHTELTE SCHACHTELN
Problembeschreibung
Problemanalyse und Entwurf der Lösung
Der Algorithmus
Das Programm
Die Programmanalyse
Aufgaben
Anmerkungen
3 GREEDY
Grundlagen
Problem 1. Rucksackproblem
Problem 2. Kartenfärbung
Problem 3. Springer auf dem Schachbrett
Problem 4. Minimaler Spannbaum (Kruskal-Algorithmus)
Problem 5. Huffman-Kodierung
4 DATA ORDERING PROBLEM
Problembeschreibung
Problemdomäne, Definitionen
DOP und DOPI sind NP-vollständig
Algorithmen für DOP und DOPI
Zufällige-Lösung-Algorithmen (RAN)
Exakt-Algorithmen (EX)
Greedy_Min-Algorithmen (GM)
Greedy_Min Simplified-Algorithmen (GMS)
Algorithmen mit unterer Schranke (LB)
Implementierungsdetails
Programm
Auswertung der Ergebnisse
Aufgaben
5 REKURSION
Vollständige Induktion
Rekursion: Grundlagen
Problem 1. Quersumme und Spiegelung einer natürlichen Zahl
Problem 2. Die Zahl 4
Problem 3. Rest großer Potenzen
Problem 4. Die Torte (lineare Rekursion)
Problem 5. Die Ackermannfunktion
(verschachtelte Rekursion, "compound recursion")
Problem 6. Rekursive Zahlenumwandlung
(Dezimalsystem in System mit Basis P)
XIV
25
25
26
27
29
32
37
38
39
39
40
43
45
48
56
65
65
66
71
72
73
74
74
75
75
77
84
94
96
99
99
105
106
108
111
115
118
120
Problem 7. Summe zweier Wurzeln (verzweigte Rekursion)
Problem 8. Collatz-Funktion (nicht-monotone Rekursion)
Problem 9. Quadrate und Quadrätchen
Problem 10. Quadrate (direkte Rekursion)
Problem 11. Quadrate und Kreise (indirekte Rekursion)
Problem 12. Die Koch’sche Schneeflockenkurve
6 TEILE UND HERRSCHE
Grundlagen
Problem 1. Größter gemeinsamer Teiler mehrerer Zahlen
Problem 2. Die Türme von Hanoi
Problem 3. Integral mit Trapezregel
Problem 4. Quicksort
Problem 5. Mergesort (Sortieren durch Verschmelzen)
Problem 6. Quad-Bäume
Problem 7. Diskrete Fourier-Transformation (DFT)
7 BACKTRACKING
Problem 1. Das Problem der n Damen
Allgemeine Bemerkungen zum Backtracking-Verfahren
Problem 2. Das Problem der n Türme
Problem 3. Das Problem der Türme auf den ersten m Reihen
Problem 4. Das Problem der aufsteigenden Türme
auf den ersten m Reihen
Problem 5. Die Freundschafts-Jugendherberge
Problem 6. Partitionen einer natürlichen Zahl
Problem 7. Erdkunde-Referate
Problem 8. Alle Wege des Springers
Problem 9. Das Fotoproblem
Problem 10. Der ausbrechende Ball
Problem 11. Orangensport
Problem 12. Testmusterkompaktierung
Problem 13. Sudoku
Problem 14. Das Haus des Nikolaus
Noch 10 Probleme
8 DYNAMISCHE PROGRAMMIERUNG
Grundlagen, Eigenschaften des Verfahrens
1. Ursprung des Konzeptes
2. Optimalitätsprinzip
3. Überlappung der Probleme, Speicherung der optimalen
Teilproblemlösungen (Memoization)
4. Einführendes Beispiel – die Fibonacci-Folge
5. Bottom-up versus top-down
123
125
127
130
133
135
145
145
146
148
150
152
155
157
162
169
169
175
178
179
180
181
182
185
188
191
193
196
205
214
221
224
231
231
231
231
232
232
234
XV
6. Vergleich mit anderen Verfahren
Aufgaben
Problem 1. Das Zählen der Kaninchen
Problem 2. Längste aufsteigende Teilfolge
Problem 3. Längste gemeinsame Teilfolge (LCS)
Problem 4. Zahlen-Dreieck
Problem 5. Domino
Problem 6. Verteilung der Geschenke
Problem 7. Ähnliche Summe
Problem 8. Schotten auf dem Oktoberfest
Problem 9. Springer auf dem Schachbrett
Problem 10. Summen von Produkten
Problem 11. Minimale Triangulierung eines konvexen Vielecks
Problem 12. Multiplikation einer Matrizenfolge
Problem 13. Edit-Distanz
Problem 14. Arbitrage
9 POTENZSUMMEN
Problembeschreibung
Problemanalyse. Algebraische Modellierung
Von der Rekursionsgleichung zum Algorithmus
Der Algorithmus
Programm
Aufgaben
234
235
236
240
245
249
253
258
261
266
275
280
286
291
297
305
311
311
311
313
316
318
321
LITERATURVERZEICHNIS
323
STICHWORTVERZEICHNIS
327
ȱ
ȱ
XVI
Algorithmen – grundlegende Konzepte
1
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱ
ȱȱ £ȱȱǯȱȱȱȱ £ǰȱȱȱȱȬ
ȱǰȱȱ ȱ§ȱǰȱ ȱȱȱ£ȱȱ
ȱȱȱ£ûǯȱ
ȱ
Abstammung des Wortes Algorithmus
ȱ ȇȱȱȱȱȬ £ȱǻǯȱŝŞŖȮŞśŖǼȱ ȱ
ȱ ȱ ǰȱ ǰȱ ȱ ȱ
ǯȱȱȱȱȱȱȬ £ȱ
ǻǼȱ ȱ ȱ ȱ ǮȄǯȱ ȱ ȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
£ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ǰȱ ȱ ȱ Ȭȱ ȂȬǰȱ ȱ ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
£ȱ Ȭ £ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ £ȱ ãǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȬȱȱȱǯȱȱ
Alternative Definitionen
ȱ đȱȱ £ȱãȱ ȱȱȱȱDZȱ
• ȱȱȱȱȱǰȱȱȱȱãǯȱȱȱãȱȬ
ȱȱȱȱȱȱûȱ ǯȱ
• ȱȱȱȱȱ ǰȱȱȱȱȱȱ£ȱ
ȱȱȱȱãȱûȱȱ £ȱȱȱȱ
ǯȱ
• ȱȱȱ£ȱ ȱǰȱȱȱȱȱȱȱ ûȱ
ȱǯȱ
2
Grundlegende Algorithmen mit Java
•
•
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ¢ȱ ȱ
ȱȱȱȱûȱ ǯȱ
Beispiele für Algorithmen
Euklidischer Algorithmus.ȱȱȱǰȱ ȱ ȱȬ
ȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ǯȱ ȱ ȱ ¡£ȱ ȱ ȱ ȱ ȱ
ǯȱ ȱ ȱ ȱ ȱ ǰȱ ȱ
ȱ ǯȱ řŖŖȱ ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ǯȱ ãđȱ ȱ ȱ ȱ ȱ Ǯȱ
ȃȱ ǰȱ ȱ ȱ ŗřȱ ûȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ȱ £Ȭ
ȱǯȱȱ
ȱ
ȱ
ȱȱȱǰȱȱȱȱȱȱDZȱȱǰȱȱ∈ȱWȱȱ
ȱ ȱȱȱŗȱƽȱȱȱŗȱƽȱǯȱȱȱȱȱǻǰȱǼǰȱȱȱȱƽȱƸȱȱŖȱri
ǀȱ ǯȱ ûȱ ȱ ȱ ¡ȱ ȱ ȱ đȱ Ƹŗƽȱ ȱ Ƹŗƽǯȱ ȱ ȱ ȱ ȱ
¡ȱǰȱȱȱȱƽȱŖȱǯȱûȱȱȱȱǻǰȱǼȱƽȱȬŗȱ ǻãđȱȱȱ
ȱȱȱǼǯȱȱȱȱDZȱ
ȱ
ȱȱ
ȏ ȱ
ȱ
ŗǯ ȱǰȱȱzȱWǰȱȱǃȱȱǁȱŖȱ
ȱ
Řǯȱȱȱȱŗȱbȱǰȱŗȱbȱǰȱȱbȱŗȱ
ȱ
řǯ ȱǻȱ≠ȱŖǼȱȱ
ȱ
řǯŗǯȱȱƸŗȱbȱȱ
ȱ
řǯŘǯȱȱƸŗȱbȱȱǻƽȱȱǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱřǯřǯȱȱȱȱȱȱȱbȱƸŗȱ
ȱ
ȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱŚǯȱȱȱȱǻǰȱǼȱƽȱȬŗȱ
ȱ
ȏ
ȏ ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
1 Algorithmen – grundlegende Konzepte
DZȱ
ȱ
a = 294, b = 77
294 = 3 x 77 + 63
77 = 1 x 63 + 14
63 = 4 x 14 + 7
14 = 2 x 7 + 0
3
a = 2521, b = 338
2521 = 7 x 338 + 155
338 = 2 x 155 + 28
155 = 5 x 28 + 15
28 = 1 x 15 + 13
15 = 1 x 13 +
2
13 = 6 x
2 +
1
2 = 2 x
1 +
0
ȱ
Das Sieb des Eratosthenesǯȱ ȱ ȱ ȱ
ǻǯȱ ŘŝŜȮŗşŚȱ ǯȱ ǯǼȱ ȱ ǰȱ ȱ ȱ
ǯȱ ȱ ȱ ȱ ȱ ¢ǰȱ ȱ ¢ǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ¡ǯȱ ȱ ȱ
ȱȱȱȱȱ¡ǯȱȱ ȱȱȱ
đȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
¢ȱ ȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ ȱȱȱȱȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱ§Ȭȱȱȱȱǰȱȱ
ȱȱȱ ȱȱȱȱǯȱđȱȱȱȱ ȱ ǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ £§ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ §đȱ ȱ Ȭ
ǰȱȱ£ȱǯȱȱȱȱ¡ǯȱ
ȱ
ǯȱ ȱ £ȱ ȱ ȱ ûȱ ȱ ãđȱ ȱ ŗǰȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ŗȱ ȱ ǯȱ ȱ ȱ ȱ ãđȱ ȱ ŗȱ ȱ ȱ £Ȭ
£ǯȱ
ȱ
ȱȱȱȱȱȱǰȱ ȱȱȱûȱȱȬ
ȱ ǰȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
ȱ ȱ Řǰȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
ȱ řǰȱ śǰȱ ŝdzȱ ǯȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ãǰȱ
ȱȱȱđȱȱǯȱ ȱȱǰȱȱȱ£ȱǰȱ
ȱȱȱȱȱûȱȱȱDZȱ
ȱ
ȱ
ȱ
ȱ
4
Grundlegende Algorithmen mit Java
ȏ ȏ ǻǼȱ
ŗǯ ȱȱȱûȱȱȱŘȱȱȱǯȱ
Řǯ ȱ←ȱŗȱ
řǯ ȱ
řǯŗǯ ȱȱ←ȱȱǰȱȱãđȱȱȱȱȱȱȱ ȱ
ǻȱȱȱŘǼȱ
řǯŘǯ ȱȱȱŘȉǰȱřȉǰȱŚȉǰȱǯǯǯȱȱ££ȱȱ
řǯřǯ ȱ←ȱȱ
ȱǻȱȱǀȱ√ȱǼȱ
Śǯ £ȱ←ȱȱȱȱ
śǯ ȱȱȱȱ£ȱ£ ȱŗȱȱǯȱ
ȏȱ ȏ ȏ ǻǼȱ
ȱ
DZȱ
ȱ
ȱȱȱȱŘȱ
ȱȱȱȱśȱ
ȱȱȱȱřȱ
ȱ
ȱ£ȱȱŚŞȱ
ȱ
ȱ
Binäre Suche.
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȱ ȱ ȱ ȱ ¡ȱ
ǯȱȱȱȱȱȱȱȱȱǰȱȱȱȱȱȱȱȱ
ȱ¡ȱûǯȱȱȱȱtȱǰȱȱ ȱŖȱ£ûǯȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ £ȱ ȱ ǯȱ ȱ §ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱ¡ȱ£ȱȱȱ£ȱȱǰȱȱȱȱ
ȱ§ǯȱ
ȱ
1 Algorithmen – grundlegende Konzepte
5
ȱ
ȏ ȏ ȱ
ȱ
ŗǯ ȱ¡ǰȱŗǰȱŘǰȱǯǯǯǰȱȱ
ȱ
Řǯ ȱȱ←ȱŗǰȱȱ←ȱȱ
ȱ
řǯ ȱǻȱȱǀȱȱǼȱȱ
ȱ
řǯŗȱȱ m ← ª i + j º ȱ
ȱ
« 2 »
¬
¼
ȱ
ȱǼȱȱȱ←ȱȱƸȱŗȱ
řǯŘȱȱ
ȱǻȱ¡ȱǁȱ
ȱ
ȱȱȱȱȱȱȱȏ ȱ
ȱ
řǯřǯȱȱȱ←ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱȱȱȱȱŚǯȱȱȱ ȱǻȱ¡ȱƽȱȱǼȱȱȱ←ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱśǯȱȱȱȱȱ←ȱŖȱ
ȱ
ȱȱȱȱȱȱȱȱȱŜǯȱȱȱȱȱ
ȱ
ȏȱ ȏ ȏ ȱ
ȱ
ȱȱ
ȱȱřǯŘǯȱûȱ ǰȱȱȱȱȱ¡ȱȱȱȱȱǻȱȱȱȱ
ȱ ȱǽǰȱǾǼǯȱȱǰȱȱ ȱȱ ȱǽƸŗǰȱǾȱ ǰȱȱȱ ȱ
ǽǰȱǾȱǻȱřǯřǼǯȱ
ȱ
ȱȱǰȱ ȱȱȱûȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱ ȱȱ ȱȱ ¡ȱȱ £ǰȱ ȱ ȱ ŗŝȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ ȱ ȱ
DZȱ
ŗǰȱǯǯǯǰȱȱƽȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
¡ȱƽȱȱȱȱȱȱȦȦȱȱȱ
ȱ←ȱŗǰȱȱȱȱ←ȱŗŝȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȦȦȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱƽȱŗǰȱȱƽȱşȱȱǻřǯřǼȱǰȱȱ←ȱśȱǻřǯŘǯȱȱřǯřǯǼȱ
ȱȱƽȱŗǰȱȱƽȱŗŝǰȱȱ←ȱşȱȱǻřǯŘǯȱȱřǯřǯǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱƽȱśǰȱȱƽȱşȱȱǻřǯŘǼȱǰȱȱ←ȱŝȱǻřǯŘǯȱȱřǯřǯǼȱ
ȱƽȱŝǰȱȱƽȱşȱȱǻřǯŘǼȱǰȱȱ←ȱŞȱǻřǯŘǯȱȱřǯřǯǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱ£ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱƽȱǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱƽȱŝǰȱȱƽȱŞȱȱǻřǯřǼȱǰȱȱ←ȱŝȱǻřǯŘǯȱȱřǯřǯǼȱ
ȱƽȱŝǰȱȱƽȱŝȱȱȱȱ
ȱ
ȱ
6
Grundlegende Algorithmen mit Java
Rezept für Tiramisu.
ȱ
ȱ
DZȱ
ŗȱ
đȱ
ȱ
ǻŘŖŖȱ
Ǽȱ
ãǰȱ śŖŖȱ ȱ ǰȱ Śȱ ǰȱ Řȱ
ãȱ ǰȱ śȱ ãȱ ǰȱ ȱ
ǰȱŗȱȱ ǯȱ
ȱ
ȱ
ȱ
ȏ ȱ
ŗǯ ȱ ȱȱȱȱđǯȱ
Řǯ ȱȱ£ȱȱ ȱ§ǯȱ
řǯ ȱȱȱȱȱȱȱȱǯȱ
Śǯ ȱȱ đȱǯȱ
śǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
ȱǯȱ
Ŝǯ ȱ£ȱȱȱǰȱȱȱȱ ǯȱ
ŝǯ ȱ đȱȱȱȱ§ȱȱǯȱ
Şǯ ȱȱ đȱ£ȱȱ£ǯȱ
şǯ ȱ ȱ ȱ ȱ ȱ §đȱ ȱ ȱ §ȱ ȱ ȱ
û£ǯȱ
ŗŖǯ ȱȱȱȱ§ȱȱǯȱ
ŗŗǯ ȱȱȱȱ§đȱǯȱ
ŗŘǯ ȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ ǰȱ ȱ ȱ
ûȱǯȱ
ŗřǯ ȱȱȱȱ ȱǯȱ
ȏȱ ȏ ȱ
ȱ
ǰȱȱȱȱȱȱȱ£ȱȱȱȱǯȱ
ȱ ȱ £ȱ ûȱ ǰȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ ȱ
ȱ ǯȱ ȱ ȱ £ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ǻǼȱ ûȱ ȱ ȱ ǻǼȱ ȱ ȱ ȱ
ȱ ǻǼȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ
ȱȱûȱ ȱȱȱŗŘȱȱŗŗȱ ûǰȱ ȱ ȱ ȱȱŗřȱ
ǻȱ ȱǼȱȱŗŘȱǰȱȱȱȱȱǯȱ
ȱ
1 Algorithmen – grundlegende Konzepte
7
ȱȱȱ ȱǰȱȱȱȱȱȱǰȱȱ£ȱȬ
ȱãȱȱûǯȱȱȱ ǰȱȱȱ§ȱȱȱ
ǰȱ ȱ ȱ ȱ ããǯȱ ȱ ãȱ ȱ £ ȱ £ȱ
ǰȱȱȱȱȱ£ȱȱȱȱȱȱȱȱȱãȬ
ȱȱ ȱ§ȱ ǯȱȱȱȱȱ ȱȱȱ
ãǯȱȱûȱãȱ ȱȱȱȱȱǰȱȱȬ
ȱ£ǯȱ
Vom Problem zur Lösung
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ đȱ
ǰȱȱ ȱǯȱȱȱȱȱȱȱȱ
ȱ£ ȱDZȱȱȱǯȱȱ
• ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǻ ȱǰȱǰȱãǼDzȱ
• ȱ ȱ ȱ £ȱ £ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ £ȱ
£ǯȱ
ȱ ¢ȱ
ȱ ȱ ȱ ǻǼȱ ȱ ȱ
ãȱ £ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ǯȱ ȱ £ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱȱ£ȱãȱȱȱȱ£ǰȱȱȱȱǯȱȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ ¡§ȱȱȱȱȱ §ȱȱ§ǯȱ
ȱ
ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ûȱ DZȱ
ȱ
• ȱ ȱ ȱ ¢ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
£ȱȱ ȱãȱǻǼǯȱ
• ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱȱ ûȱȱǯȱ
• ȱ ȱȱȱȱȱǯȱ
ȱ
ȱŗǯȱ §ȱǻǯȱȱȱǼǯȱȱ
ȱȱȱ ȱȱ§ǰȱ§ǰȱǰȱ ȱȱ£ȱȱ
ȱȱȱȱǰȱȱ ȱȱȱȱȱ§ǰȱȱ£ ȱ
ȱȱȱȱȱǯȱ
ȱ
ȱ
ȱ
8
Grundlegende Algorithmen mit Java
ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ãǰȱ ûȱ ȱ £ȱ ȱ ¢ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ǰȱ
ȱȱȱûȱȱȱŗȱȱȱ££ ǯȱ £ȱûȱ ȱȱȱ
ȱ ǰȱ ȱȱȱȱǯȱȱȱȱ£ ȱ
¡ȱȱȱȱȱȱȱǯȱȱȱȱȱȱȬȱȱȱȬȱȱȱ
§ȱ ȱ ȱ ŗǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ Ŗǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱ ȱ ƽȱ ǯȱ ȱ §ȱ ȱ ȱ ȱ ȱ ûȱ
ȱȱŗȱȱǯȱȱãȱȱ ȱȱȱ¢ȱȱƽȱǿŗǰȱŘǰȱdzǰȱȀǰȱȱ∈ǿŗǰȱ
ǯǯǰȱȀȱȱǯȱȱûȱȱǰȱȱȱȱ≠ȱǰȱ ȱȱƽȱŗȱǯȱȱ
ȱȱȱȱǰȱȱ ȱȱȱȱǰȱȱȱ
§ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ ȱ ȱ ȱ ȱ
ȱ§ȱǯȱ
ǯȱȱ ȱȱ ȱ[ȱȱřȱãȱȱ§ǰȱȱȱ
§ȱȱȱDZȱ
ȱ
ȱ
ȱ
ȱ§ȱȱ ȱ ȱȱȱ ȱ£ǯȱȱǰȱȱȱ
ȱ£ ȱ ȱȱǯȱȱ
ȱ ££¡ȱ ȱ ¢ǰȱ ȱ ȱ ȱ ƽȱ ȱ ûȱ ȱ ǰȱ ȱ zȱ ǿŗǰȱ Řǰȱ dzǰȱ ŗŖȀǯȱ ȱ
ãȱȱȱǿȱÁ
ÁÁ
ÁÁ
ÁȱȀǯȱ
ȱ
ȱ
ȱ
1 Algorithmen – grundlegende Konzepte
ȱȱ ȱ
ȱ
ȱ
1
4
7
2
5
3
6
8
9
9
ȱ££¡ȱş¡şȱ
§0 1 0 0 0 0 0 0 0·
¨
¸
¨1 0 1 1 0 0 0 0 0¸
¨0 1 0 1 1 1 0 0 0¸
¨
¸
¨0 1 1 0 1 0 0 0 0¸
¨
¸ȱ
¨0 0 1 1 0 1 1 1 0¸
¨0 0 1 0 1 0 0 1 0¸
¨
¸
¨0 0 0 0 1 0 0 1 0¸
¨0 0 0 0 1 1 1 0 1¸
¨¨
¸¸
©0 0 0 0 0 0 0 1 0¹
ȱ
ȱãȱ§ȱȱ ȱȱ ȱȱȱ§ȱȱȱ DZȱ
ȱ
ȱ
1
2
3
ȱ
ȱ
ȱ
5
6
4
ȱ
ȱ
ȱ
7
9
8
ȱ
ȱ
ȱ
10
Grundlegende Algorithmen mit Java
ȱŘǯȱȱȱȬǯȱ
ȱ ȱûȱȱȱȱ§ȱȱȱǯȱȱ
ȱȱ ȱ£ǰȱ ȱȱ ȱȱȱ£ ǯȱ ȱǰȱȱ
đȱȱǰȱȱ ȱȱȱȱȱȱ ȱȱ
ȱ§ǯȱȱȱȱ ȱȱȱǰȱ ȱȱȱȱȱǰȱȱ
¢ȱ ȱ £ȱ ǯȱ ȱ ȱ ȱ ǰȱ ǰȱ §ȱ
ǻ ãǰȱǰȱǼǰȱȱȱȱȱȱûȱȱ£ǯȱ
ȱȱ ȱȱȱǰȱȱȱȱãȱûȱ ȱ
ûȱ ǻȱ ȱ ȱ ȱ ȱ Dzȱ ȱ ȱ ȱ ȱ
ȱ ȱ§ȱȱȱȱȱDzȱȱȱ
§ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ Dzȱ ǯǯǯǼǯȱ
ȱ ȱ §ȱ ȱ ȱ ȱ ǻȱ ȱ ãȱ
ȱ ȱ ȱ §ǰȱ £ǯȱ ǯȱ ȱ ǰȱ ȱ Dzȱ ȱ ȱ ȱ
ȱ £ȱ ȱ £ ȱ §ȱ Dzȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
£ȱ ¡ȱ ȱ ȱ Dzȱ ǯǯǯǼǯȱ ȱ ȱ ȱ ȱ §ȱ ȱ ǰȱ
ãȱ ȱȱȱ ȱȱȱǯȱ
Eigenschaften eines Algorithmus
•
•
•
•
•
•
•
ȱãȱȱǻȱǼȱ
ȱȱȱǻȱǼȱ
ȱ ǻȱ ȱ ûȱ ȱ ȱ ȱ £ ȱ ȱ
§ȱȱȱǼȱ
ȱȱȱȱ£ȱȱȱ
ȱ ǻȱ ȱ ȱ ûȱ ȱ £ȱ ȱ ȱ
ȱȱȱȱǼȱ
¡§ȱ ǻ ǰȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
£ǰȱȱ Ǽȱ
ȱ ǻȱ ȱ ȱ ûȱ ȱ ȱ ȱ £ȱ
ȱ ǰȱȱȱȱûǰȱȱûȱȱȱ
Ǽǯȱ
Algorithmik
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
¢ȱȱȱ§ǰȱȱȱȱ¢ȱȱ
ȱǯȱ
ŗǯ ȱǮ Ȅȱȱȱ£ ȱDZȱ
• ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻȱ
ǰȱȱȱȱ§ȱȱȱȱ
ǰȱ ǯǼȱ
1 Algorithmen – grundlegende Konzepte
11
•
Řǯ
ȱ ȱ ǯȱ ȱ ȱ ȱ ûȱ ȱ £ȱȱ
ȱûȱãȱǯȱ
ȱȱ¢ȱȱȱ ȱȱȱ£ȱ ǰȱ
ȱ ȱ ãȱ £ȱ ȱ £ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ £ȱ ȱ ȱ §ȱ ǻ£ȱ
§ȱǼǯȱ
ȱ
ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱȱȱȱǰȱȱ£ȱȱȱȱ
£ȱ ǰȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ
û£ȱ ȱ ûȱ ȱ ȱ ȱ ȱ §ȱ ǯȱ ȱ §ȱ
ȱ ȱ ȱ ȱ ǻȱ ȱ Ǽǰȱ ȱ ȱ ȱ ȱ DZȱ
ǰȱ ǰȱ ȱ ǰȱ Ȃȱ ǰȱ
ǰȱ ǯȱ
Das RAM-Rechnermodell
ȱ ȱȱȱ§ȱȱȱȱȱȱȱ
ȱ ¢ȱ ǰȱ ȱ ȱ ȱ ȱ ǻǼȱ đǯȱ ȱ Ȭ
ȱȱȱDZȱ
•
ȱǮȄȱȱǻƸǰȱȬǰȱȘǰȱȦǰȱƖǰȱƽǰȱȦ ǰȱȦǼȱãȬ
ȱȱȱ£ ǯȱȱǯȱ
• ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ ǯȱ ȱ
ǯȱȱ£ȱȱȱȱȱȱ£ǯȱ
ȱ §ȱ£ȱȱǰȱȱȱǻǼȱȱȱ££ ǰȱ
ȱȱȱ§ȱǰȱȱȱȱ£ȱȱȱȱŗŖǯȱȱ
ǰȱȱȱȱȱȱǻǼȱãǰȱ§ȱȱȱ
£ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ đȬ
ǯȱ
•
ȱ £ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
£ȱȱ£ȱûǯȱȱȱûȱǰȱȱȬ
ȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ ǻ£ǯȱ ǯȱ ȱ Ǽȱ
ǯȱȱȱȱ¢ȱȱǯȱ
ȱȱȬȱȱȱȱ£ȱȱȱǻǼǰȱȱûȱ
ȱ ȱ ȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ
ȱȱȱ§£ǰȱ ȱȱȱȱ£ȱ ȱȱȱȬ
ȱ£ȱȱ§ǯȱ £ȱȱȱǰȱȱȱȱ£ȱȱ
ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ǰȱ ȱ ȱ ûȱ
§£ȱ£ȱãǯȱȱȱ ȱȱȱȱǰȱȱȱȱ
¡ȱȱȱȱȱȱȱȱǯȱȱȱȱȱ
ǰȱȱȱȱȱǰȱȱȱȱȱȱȱȬ
12
Grundlegende Algorithmen mit Java
ȱ ȱ £ȱ ȱ £ ǯȱ ȱ ȱ ǯȱ £ȱ ȱ ȱ ȱ
ȱȬȱȱȱ ǰȱȱȱȱȱȱ£ȱȬ
¢ǯȱȱȱȱ ȱȱȱ ȱȱȱ£ȱȱ
§ȱȱ ǯȱȱ
ȱ
ȱȱȱ £ǰȱȱȱȱȱ£ȱ ȱǯȱȱ ȱ
£ȱȱȱȱȱȱȱǯȱȱȱǰȱȱȱȱȱ
ȱ ǰȱ ȱ ȱ ȱ §ȱ ãȱ ǯȱ ȱ ȱ ȱ ȱ £ǰȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭ
ûȱûǰȱȱȱȱ ǯȱȱ §ȱȱǰȱȱȱ
ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ £ǯȱ
ȱ§ȱȱȱȱȱȬǯȱȱȱȱǰȱȱȱȬ
ǰȱȱȱȱǰȱȱû£ȱǰȱȱȱȱȱȱ
§ȱ£ȱǯȱȱ
Die Komplexität von Algorithmen
ȱ ¡§ȱȱȱȱȱȱ ǰȱȱȱ ȱ
ȱȱȱ ȱǻ£ǰȱãȬ
ȱ ǰȱ £ȱ ȱ ȱ ǯǼǯȱ ȱ
ȱ ȱ ȱ ȱ ¡ȱ ȱ ǰȱ ǰȱ ȱ ȱ
£ȱȱȱȱ ȱǯȱȱ
ȱ
ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱȱ
ǻǼȱ ȱ ǰȱ ȱ ȱ £ȱ §ȱ
ûȱȱȱȱȱȱȱǯȱȱȱ
ȱȱȱȱȱȱȱǰȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻȱ ȱ £ȱ ȱ ȱ
ȱ Ǽǰȱ ȱ ǻȱ ȱ £ȱ ȱ ȱ ȱ
Ǽǰȱ ǰȱ ǰȱ ǰȱ Ȭ
ǰȱȬȱ ǯȱǯȱ
ȱ
Die Ĭ-, O- und ȍ-Notation.ȱȱȱ ȱ ǰȱȱȱȱ
ȱ ¡§ȱ ȱ ȱ £ȱ ¢ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǯȱ
ȱ
Die Ĭ-Notation (konstante Kategorie – same order).ȱȱȱȱȱ ȱ
Ŗȱ zWȱȱŗǰȱŘȱzȱ[ȱǰȱûȱȱȱȱȱǻǼȱûȱȱûȱȱǰȱȱ
ãđȱȱŖȱǰȱȱ£ ȱŗȱȉȱǻǼȱȱŘȱȉȱǻǼȱǰȱȱȱ ǰȱȱȱ
zȱ̋ǻǼȱǯȱ
1 Algorithmen – grundlegende Konzepte
13
ȱ
ȱ̋ȬDZȱ∃ŖǰȱŗǰȱŘȱ∀ȱ≥ȱŖDZȱŗȉǻǼȱ≤ȱǻǼȱ≤ȱŘȉǻǼȱȱ
ȱ
Die O-Notation (obere Schranke – upper bound). ȱ ǰȱ ȱ ǻǼȱ zȱ ǻǻǼǼȱ ǰȱ
ȱȱȱȱ ȱŖȱzWȱȱȱz[ȱǰȱûȱȱȱȱȱǻǼȱûȱ
ȱûȱȱǰȱȱãđȱȱŖȱǰȱȱȱȱȉǻǼȱǯȱ
ȱ
ȱ
ȱȬDZȱ∃Ŗǰȱȱ∀ȱ≥ȱŖDZȱǻǼȱ≤ȱȉǻǼȱ
Die ȍ-Notation (untere Schranke – lower bound).ȱ ȱ ǰȱ ȱ ǻǼȱ zȱ ̛ǻǻǼǼȱ ǰȱ
ȱȱȱȱ ȱŖȱzWȱȱȱz[ȱǰȱûȱȱȱȱȱǻǼȱûȱ
ȱûȱȱǰȱȱãđȱȱŖȱǰȱȱãđȱȱȉǻǼȱǯȱ
ȱ
14
Grundlegende Algorithmen mit Java
ȱ
ơ̇̄ȬDZȱ∃Ŗǰȱȱ∀ȱ≥ȱŖDZȱǻǼȱ≥ȱȉǻǼȱ
Optimalität, Reduktion, Beispiele
ȱ ¡§ȱȱȱȱȱȱǻǼǰȱȱȱ£ȱȱãȬ
ȱȱǻȱȱ£ǼȱȱȱûȱȱȱȱȱȱȬ
§ǯȱȱȱ£ ȱ ȱȱȱDZȱ
ǯ ȱ ¡§ȱ ȱ ûȱ ȱ ǻǯȱ Ȭȱ ¡¢ǼDZȱ
ȱ£ȱȱȱȱȱȱ§ȱȱȱȱȱ
ǯȱ
ǯ ȱ£ȱûȱȱȱȱȱȱȱȬ
ȱȱ£ȱȱ £ȱȱǯȱ
ȱ ȱ ȱǰȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ Ȭ
§ȱǰȱ£ǰȱ ȱȱȱȱȱ§ȱȱȱ ȱ
ǻǯȱ ȬǼǯȱ ȱ ȱ §ȱ ȱ ȱ ¡§ȱ ȱ ǻǼȱ ȱ ȱ ȱ
ǻǻǼǼȱ ǰȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ DZȱ ȱ ǻȱ
¡§Ǽǰȱ ǻǼȱ ǻȱ
¡§Ǽǰȱ ȱ ûȱ ≥Řȱ ǻ¢ȱ
¡§Ǽǰȱ ȱǻ¡ȱ ¡§ǼǰȱǷȱǻȱ ¡§Ǽǯȱȱȱ
ȱȱȱȱ £ ȱȱȱ¢ǯȱûȱȱ
£ǰȱ ȱ ȱ £ ȱ ȱ ǻǼȦǻǼȱ ûȱ ȱ ȱ ȱ ¡ȱ ȱ
ȱǰȱȱǻǼȱȱȱǻǻǼǼǯȱDZȱ
ŗǯ
Řǯ
řǯ
Śǯ
n
= 0 ȱmȱ n ȱzȱǻǼȱ
n→ ∞ n
n
lim
= ∞ mȱȱ{ȱǻ n Ǽȱ
n →∞ n
n 1
lim
= mȱȱzȱǻŘǼȱ
n → ∞ 2n
2
2n
lim
= 2 mȱŘȱzȱǻǼȱ
n→∞ n
lim
1 Algorithmen – grundlegende Konzepte
15
ȱȱȱđȱȱ §ǰȱȱȱȱûDZȱ
ǻǼȱǀȱȱǀȱȱȉȱǻǼȱǀȱŘȱǀȱřȱǀȱŘǰȱȱȱȱǻǻǼǼȱ£ȱǻǼȱ£ȱǻȱǻǼǼȱ£ǻŘǼȱ
£ȱǻřǼȱ£ȱǻŘǼǯȱȱ
DZȱŗŖȱƸȱśȱǻǼȱƸȱŞȱȱ∈ȱǻǼǰȱŞȱ∈ȱǻŘǼǰȱŜśȱȱ∈ȱǻŗǼǰȱŗŖŖŖȱȱ∈ȱǻŘǼǯȱ
ȱ
ȱȱ ¡§ȱȱȱȱ ǰȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱûȱȱȱȱȱȱǰȱ ȱ
ȱ ¡§ȱ ȱ ȱ ȱ ûȱ ȱ ¡§ȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ãǯȱ
ȱ ȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱȱȱȱȱǰȱȱûȱȱȬ
n
ȱ §¨ ·¸ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
¨ 2¸
© ¹
ȱ ȱ ȱ ¡§ȱ ǻŘǼǯȱ ȱ ãȱ ȱ £ǰȱ ȱ ȱ
ȱȱ ¡§ơ̇̄ǻŘǼȱǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ Ȭ
ǰȱ ȱ ȱ ¡§ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ȱ
§ȱ ȱ £ȱ ǯȱ
ǰȱ ȱ ȱ ȱ ȱ
ȱûȱȱȱȱȱȱ
ûȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱȱȱȬ
ǰȱȱ ȱȱȱ
ȱãȱȱȱǰȱȱȱȱȱ ȱãǰȱȱȱȱȱȬ
ȱ ȱ ȱ ǯȱ ȱ ȱ§ȱ ȱ ȱ ȱ ȱ ¡ȱ ûȱ ȱ
ȱȱȱȱȱ£ȱǻ ¡§DZȱ̋ǻȱǻǼǼǼǯȱ
DZȱǻȱƸȱǻǼǼȱƽȱǻǼǰȱȱǻǼȱǀȱǰȱǻǷȱƸȱřǼȱƽȱǻǷǼǰȱȱřǀǷǯȱ
ȱ
ȱ ȱ ȱȱȱȱȱ ¡§ȱȱ££ȱȱȬ
ȱ¢ǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
16
Grundlegende Algorithmen mit Java
¢ȱȱ ¡§ǯȱ ȱȱȱȱDZȱ
ŗǯ ȱȱ
Řǯ ȱ←Ŗǰȱȱ←ȱŖǰȱȱ←ȱŖȱ
řǯ ȱǻȱȱǀȱȱǼȱȱ
ȱȱȱ ȱ
ȱȱȱ←ȱȱƸȱŗȱ
ȱ
ȱ
ȱȱȱȱȱ←ȱȱȮȱŗȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ←ȱȱƸȱŗȱ
ȱȱȱȱȱȱȏȱ
Śǯ ȱ←ȱŖȱ
śǯ ȱǻȱȱǀȱřȱǼȱȱ
ȱȱȱ ȱ
ȱ←ȱȱȬȱŗȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱ←ȱȱƸȱŗȱ
ȱȱȱȱȱȱȏȱ
Ŝǯ ȱǰȱȱ
ȱŘȱȱřȱǯȱ
ȱ ȱ ȱ ȱ řȱ ûȱ Ř
ǰȱ ȱ ȱ ȱ ř
ȱ ǰȱ ãȱ ȱ
ȱŜȱǯȱ
ȱŚȱȱȱǯȱ
ȱ ȱ śȱ ȱ Řȉřȱ ǰȱ
řȱ ȱ ȱ řȱ ȱ
ǰȱȱȱŗŘȱǯȱ
ȱ
DZȱřƸŜƸŗƸŗŘȱƽȱŗŞƸŚȱ
ȱđȱȱ ¡§ȱȱǻǼǯȱ
ȱ
¢ȱ ȱ ¡§ȱ ȱ ££ǯȱ ȱ ȱ ȱ ȱ ǰȱ
ȱȱȱãDZȱȱȱȱȱŗȱƸȱŘȱƸȱǯǯǯȱƸȱǯȱȱ
ȱ
ȱȱ
ȱ←ȱŖȱ
ȱǻȱ←ȱŗǰȱǼȱ
ȱȱȱȱ←ȱȱƸȱȱ
Ƹŗȱ ǰȱȱ
ȱȱȱȱȱ
ȱ
ȱ
ȱ
DZȱŘȱƸȱŗȱ
ǻǼȱ
ȱȱ
ȱ←ȱŖȱ
ȱǻȱȱ←ȱŗǰȱȱǼȱȱ
ȱȱȱǻȱȱ←ȱŗǰȱȱǼȱ
ȱȱȱȱȱ←ȱȱƸȱŗȱ
ŗƸǻƸŗǼȦŘȱ ȱ
ȱȱȱȱǻƸŗǼȦŘȱȱ
ȱ
ȱ
ȱ
DZȱŘȱƸȱȱƸȱŗȱ
ǻŘǼȱ
ȱȱ
ȱ←ȱȘǻƸŗǼȱȦȱŘȱ
ŗȱǰȱȱ
ŗȱǰȱȱ
ŗȱǰȱȱ
ŗȱ ȱ
ȱ
DZȱŚȱ
ǻŗǼȱ
ȱ ȱ ȱ ȱ §ȱ ȱ ȱ ûȱ ȱ ǯȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
£ȱȱȱǯȱ
ȱ
ȱ
ȱ
ȱ
1 Algorithmen – grundlegende Konzepte
17
Wachstum von O(g(n)) – vergleichendes Beispiel
ȱ
ǻȱǼȱ
ȱȱȱǻǻǼǼȱǻȱDZƽȱǼȱ
ȱ
ȱȱȱ
Řȱ
ȱ
ȱȱ ǻȱǼŘȱ
ŗŖȱ
ŗŖŘȱ
ŗŖřȱ
ŗŖŚȱ
ŗŖśȱ
ŗŖŜȱ
Řȱ
řȱ
řȱ
Śȱ
Śȱ
Śȱ
řȱ
ŝȱ
ŗŖȱ
ŗřȱ
ŗŝȱ
ŘŖȱ
ŗŗȱ
ŚŚȱ
şşȱ
ŗŝŝȱ
ŘŝŜȱ
řşŝȱ
ŗŖȱ
ŗŖŖȱ
ŗŖŖŖȱ
ŗŖǯŖŖŖȱ
ŗŖŖǯŖŖŖȱ
ŗǯŖŖŖǯŖŖŖȱ
řřȱ
ŜŜŚȱ
şşŜŜȱ
ŗřŘǯŞŝŝȱ
ŗǯŜŜŖǯşŜŚȱ
ŗşǯşřŗǯśŜşȱ
ŗŖŘȱ
ŗŖŚȱ
ŗŖŜȱ
ŗŖŞȱ
ŗŖŗŖȱ
ŗŖŗŘȱ
Řȱ
Ƿȱ
ŗŖřȱ
ŗŖřŖȱ
ŗŖřŖŗȱ
ŗŖřǯŖŗŖȱ
ŗŖřŖǯŗŖřȱ
ŗŖřŖŗǯŖřŖȱ
ŗŖśȱ
ŗŖşŚȱ
ŗŖŗŚřśȱ
ŗŖŗşřřśȱ
ŗŖŘŚřǯřřŞȱ
ŗŖŘǯşřřǯřŜşȱ
¡§ȱûȱȱDZȱ
ŗǯ ȱȱ ǰȱȱȱȱȱȱ ¡§ȱǻǻȱ
ǼǻȱǼǼȱ ǯȱ
Řǯ ȱ ¡§ȱûȱȱȱȱȱǻǼǰȱ ȱȱûȱȱȱ
ȱȱ ȱûǯȱ
řǯ ûȱȱ§ȱȱ§ȱȱ ¡§ȱǻȱǼǰȱ ȱȱûȱ
ȱǻŗȱƸȱȱǼȱ ȱûȱ ǯȱȱ
Śǯ ȱ §ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ §ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ
ȱ ȱ ǻȱ ¡ȱ Ǽǰȱ ȱ £ȱ ȱ ȱ ǻȱ
£ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱ ȱȱȱȱȱȱȱǼǯȱȱ
¡§ȱȱȱ¡DZȱǻǼǯȱȱ
Die reelle Zeit eines Algorithmus (polynomial vs. exponentiell)
ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ §ǰȱ ȱ ǻǼȱ
ȱ ǻȱ ȱ ȱ Ǽȱ ȱ ȱ ȱ ûȱ
ǰȱȱȱȱ£ȱȱȱȱȱȱȱǯȱȱ
µsȱȱŗŖȬŜȱǯȱ
ȱȱȱȱ
ȱǻ¢ȱȱ¡ȱǼȱ
ȱ
ȱ
ǻǼȱƽȱȱ ǻǼȱƽȱȱǻǼ
ǻǼȱƽȱŘȱ ǻǼȱƽȱřȱ
śȱ
ŗŖȱ
ŘŖȱ
śŖȱ
ŗŖŖȱ
ŖǯŖŖśȱΐȱ
Ŗǯŗȱΐȱ
ŖǯŖŘȱΐȱ
ŖǯŖśȱΐȱ
Ŗǯŗȱΐȱ
ŖǯŖřȱΐȱ
Ŗǯŗȱΐȱ
ŖǯŚȱΐȱ
Řǯśȱΐȱ
ŗŖȱΐȱ
ŖǯŖŗȱΐȱ
ŖǯŖřȱΐȱ
ŖǯŖşȱΐȱ
ŖǯŘŞȱΐȱ
ŖǯŜŜȱΐȱ
Ŗǯŗřȱΐȱ
ŗȱΐȱ
Şȱΐȱ
ŗŘśȱΐȱ
ŗŖŖŖȱΐȱ
ǻǼȱƽȱŘȱ
ŖǯŖřȱΐȱ
ŗȱΐȱ
ŗŖŖŖȱΐȱ
ŗřȱȱ
Śȱ¡ȱŗŖŗřȱ ȱ
18
Grundlegende Algorithmen mit Java
ȱ ǰȱ ȱ ûȱ ȱ ≥ȱ śŖȱ ȱ £ȱ ûȱ ǻǼȱ ƽȱ Řȱ ȱ £ȱ đȱ ǯȱ ȱ
ȱȱȱȱȱȱȱȱȱȱãǰȱ ûȱȱ
ûȱȱƽȱŗŖŖȱȱŚŖǯŖŖŖǯŖŖŖȱ ȱ§ȱǯȱ
Klassifizierung der Probleme (P, NP, NP-vollständig, NP-hart)
ȱ ȱ ȱ ȱ ¡§ȱ ȱ ȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱ ǻȱ ȱ Ǽǯȱ ȱ
ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ Ȭȱ
£ǯȱ Ȭ§ȱ ȱ Ȭȱ
ȱȱȱǯȱȱȱȱȱ
£ûȱȱȱȱȱ£ȱǰȱ
ȱ
ȱ
£ȱ
ȱ
ȱ
ȱ
ǯȱ ȱ ȱ đȱ ȱ
ȱ ǰȱ ȱ ãȱ ȱ ȱ ȱ ǯȱ £ȱ
ãȱ £ȱ ȱ ȱ ȱ £ ǯȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
£§ȱ ȱ ǻǯȱ ǯǰȱ ȱ ȱ £ ȱ ȱ £ ȱ ȱ ȱ ȱ Ǽǯȱ ȱ
ȱȱȱ ȱȱȱ ȱȱ ȱ ȱǻȱǰȱȱȱ
ȱǼǰȱȱȱȱDZȱǮ ȱ ȱ£§ǵȄǯȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ãȱ ȱ ȱ ȱ ûûȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ǻȱ Ȯȱ ȱ ȱ Ǽȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱ ȱȱȱǯȱȱȱDZȱǮȱ ȱȱȱȱ
ȱ§ǰȱȱȱȱȱ ȱǵȄǯȱ ãȱȱȱȱ
ȱ ȱȱȱǯȱ
ȱ
ȱ ȱ ȱ ãȱ ȱ ǰȱ ȱ ȱ
¢ȱ
ãȱ Dzȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
NP
ȱãȱǻǼȱ ǯȱȱȱ ȱ
P
ȱ ȱ ȱ
ȱ ȱ ȱ £§£ȱ ȱ
ǰȱ ȱ ȱ ǮȬȱ
¢Ȅȱ ãȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱDZȱûȱȱ £ȱȱǰȱȱȱȱǮ Ȅȱãȱ ǰȱȱ
ȱȱȱȱ¢ȱȱûûȱ ǯȱȱȱ£ȱ
ȱ ȱ ȱ Ǯȱ ȱ ȱ ȱ ȱ Ȃȱ ǵȄǯȱ ȱ £ȱ Ǯ Ȅȱ ȱ
ȱ ȱ ȱ £ǰȱ ûȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ
£ȱ ȱ ȱ ȱ ȱ ǻȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ Ǽȱ ȱ ȱ ȱ
ȱ Ȃȱ ǯȱ ȱ ȱ ȱ ǰȱ £ȱ ûǰȱ ȱ ȱ ȱ ȱ Ȭ
1 Algorithmen – grundlegende Konzepte
19
ȱ£ ȱ ȱȱ Ȃȱǰȱǯȱǯǰȱȱȱûȱȱ ȱǿǰȱȀȱȱ ȱȱ ȱ
ǿǻǼǰȱ ǻǼȀȱ ȱ Ȃȱ ȱ ȱ Ȃȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
¢ȱȱȱ£ȱȱȱ ȱ ȱȱ Ȃǯȱ ȱãȱȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ §ȱ ǯȱ ȱ
£ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ƽŗŖŖȱ ǰȱ ȱ
ȱȱ ȱǮ Ȅǰȱȱȱȱȱȱ ȱȱ¡ȱŗŖŖȱȱ
ǰȱ ȱ ȱ ȱ ǻȱ ǰȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ
ȱȬȱȱȱȱǰȱȱȱûȱȱ ȱ ȱ
ȱǼȱȱ ȱǯȱȱȱȱȱȱ ǰȱȱȱ ȱȱȱ
¢ȱ£ȱȱǰȱȱȱ ȱ£ȱȱǮ Ȅȱǯȱ
ȱ
ȱ ȱ ȱ ¢ȱ £ ȱ ȱ ȱ ȱ Ǯ Ȅȱ ȱ ǮȄǯȱ ȱ
ȱ £ȱ û£ǰȱ ȱ ȱ ȱ Ǯ Ȅȱ ǰȱ ûȱ ǰȱ ȱ ȱ ȱ ¢ȱ
ȱ ȱ ãȱ ãȱ ûǯȱ ȱ ȱ ȱ ǮȄȱ ǰȱ ȱ ȱ
£ȱ ǻ ȱ ûȱ ȱ ãȱ ȱ ûǰȱ ȱ ȱ ȱ ǰȱ
ȱȱãǼǯȱȱ ȱȱȱȱȱȱ
ǰȱ ȱ ȱ ȱ £ãȱ ȱ Ȭǯȱ ûȱ ȱ ȱ ȱ
ȱȱȱȱȱDZȱǮ ȱ
ȱãȱȱȱ ȱȱ§ȱãđȱȱ ǵȄǯȱȱ
ȱȱȱǰȱȱǰȱȱȱȱ ȱ
£ȱ ȱȱȱ£ȱ ȱ Ȭȱãǰȱ ȱûȱ
ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ
ȱ ǻǮ ȄǼǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱȱȱȱ ȱȱȱȱȱDZȱ
Ǯ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ §ȱ ȱ ȱ ȱ
ǰȱȱǵȄǯȱ
Probleme NP-vollständig (NP-complete)
ȱ £ȱ ȱ ȱ ȱ ¢ȱ ȱ
ûȱ ȱ ȱ ȱ
ȱ ǯȱ
NP
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱǯȱ£ȱ£ȱȱ
NPC P
ȱ ȱ ȱ ãȱ ȱ ǯȱ ȱ
ȱ ȱ ȱ ȱ ȱ
ǰȱȱȱȱȱ ȱǯȱ ȱ ȱ
đȱ Ȭ§ȱ ǻǯȱ ȬǼǰȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
£ȱȱǰȱȱȱ£ȱȱ ȱȱ£§ǰȱȱȱ
£ȱȱǯȱȱ
20
Grundlegende Algorithmen mit Java
ȱȬ§ȱDZȱ
•
Ȭȱ ǻ ȱ ȱ ǼDZȱ ȱ £ ȱ Ȭ
ȱ ȱǵȱ
•
§ȱ ǻ ȱ ȱ ǼDZȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ûȱ ȱ ȱ ≥ȱ ŗȱ ǯȱ DZȱ ȱ Ȭ§ȱ ȱ Ȭ
ȱ ȱȱȱãǰȱȱ ȱȱ ȱȱȱȱȱŗǰȱŘǰȱ
dzǰȱȱ£ȱ§ǰȱȱȱ ȱȱȱǯȱ ȱ
ȱȱȬ§ȱȱ ǵȱ
• ȱ DZȱ ¡ȱ ȱ ȱ ûȱ ȱ ȱ ȱ §ǰȱ
ȱȱ§ȱȱȱȱȱǰȱȱȱȬ
ȱȱǵȱ
• ȱǻȱȱǼDZȱȱȱȱȱȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱ ȱȱȱȱȱȱ ȱǵȱ
• ûȱǻȱȱǼDZȱȱȱȱȱǰȱ
ȱȱȱȱȱȱȱȱûȱȱȱǯȱ ȱ
ȱȱãǰȱȱȱȱȱ¡ȱȱȱȬ
£ǵȱ
• ȱǻ ȱǼDZȱȱȱȱȱȱȱ £§ȱ
ǰȱȱȱȱȱȱȱ ãđȬȱȱ ȱȱȬ
ȱȱȱȱǯȱ ȱȱȱȱȱǰȱûȱȱǰȱ
ȱȱȱȱãȱȱđȱȱȱȱ ȱǵȱ
Das Erfüllbarkeitsproblem (SAT)
ȱ ȱ ȱ ȱ ȱ ûȱ ŗşŝŗȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢Ȭ
ȱ ȱ ¢ȱ ȱ ǰȱ ǯȱ ŗśŗȬŗśŞǰȱ ǯȱ ȱ Ȭ
ȱ
ǰȱ
ȱ
ȱ
ȱ
ȱ
ûȱǻǰȱȱengl. satisfiabilityǼǰȱȱ
ȱ ȱ ȱ ǰȱ
Ȭ§ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ £ȱ ȱ ȱ Ȭȱ ȱ
ȱ ǰȱ ȱ
ȱ ȱ Ȭ§ȱ
ȱ ãȱ ǰȱ ȱ ȱ ȱ ¢ȱ
ȱ ȱ Ȭ§ȱ ȱ ãǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ
Prof. Dr. Stephen Arthur Cook
ȱ
DZȱ
ȱ
ȱ
ȱ
(geb. 1939)
¢ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱȱ ȱȱãǰȱȱ¡ȱûȱȱȬ
ȱȱ¢ȱȱȱãǯȱȱ
1 Algorithmen – grundlegende Konzepte
21
ȱ ȱ Ȭǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡§ȱ
DZȱ
ȱ ȱ ȱ ȱ ȱ ûǵȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ£ȱȱǰȱûȱȱȱȱ ȱǵȱȱ
ȱ
ǯȱȱǰȱȱȱȱȱǻ Ǽȱǰȱȱȱȱ
ȱ
( y11 ∨ y12 ∨ ... ∨ y1n1 ) ∧ ( y11 ∨ y12 ∨ ... ∨ y1n 2 ) ∧ ... ∧ ( y11 ∨ y12 ∨ ... ∨ y1n m ) ǰȱ
ȱ
ȱȱ¢ȱȂȱȱȱȱȱǿ¡ŗǰȱ¡Řǰȱdzǰȱ¡ǰȱ"¡ŗǰȱ"¡Řǰȱdzǰȱ"¡Ȁȱ
ǯȱȱ
ȱ
ȱȱȱȱ Ȭȱ
ȱƽȱǻ¡ŗȱ∨ȱ"¡ŘǼȱ∧ȱǻ¡Řȱ∨¡řǼȱ∧ȱǻ"¡ŗ∨"¡Ř∨"¡řǼȱ∧ȱǻ¡ŗ∨"¡řǼȱ
ǰȱȱ ȱûȱ ǰȱȱȱȱ ȱȱȱ¡ŗǰȱ ¡Řǰȱ ¡řȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ǰȱȱ
ȱȱ£ ȱȱ ȱǯȱ
ȱ
¡ ŗȱ
¡Řȱ
¡řȱ
ȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
ŗȱ
Ŗȱ
ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
Ŗȱ
ŗȱ
ŗȱ
ŗȱ
ŗȱ
Ŗȱ
ŗȱ
ŗȱ
ŗȱ
ŗȱ
Ŗȱ
Die Klasse der NP-harten Probleme
ȱȱȱ ȱȬȱȱȱȱȱȱ ǰȱ
ȱȱȱȱ ǰȱȱȱȱȱȱ ȱȱ ȱ
ȱ Ȭǯȱ Ȭȱ ȱ £ȱ ȱ ȱ ǰȱ
ȱ ȱ Ȭ§ȱ ȱ ǻ ȱ ȱ ȱ ȱ ȱ
Ǽǯȱȱȱȱǰȱȱȱ£ȱûȱȱȱ
ȱ ȱ ãȱ £ȱ ǰȱ ǯǯȱ ȱ ȱ ȱ ãǰȱ ȱ
ȱãȱ£ȱǯȱ ȱȱ£ȱ ȱȱ ȱȱȱȱ
ȱǰȱȱûȱȱȱãȱǰȱȱǮȱȱ ȱ
ãȄȱ ǯȱ £ȱ ãȱ ǯǯȱ §ȱ ǰȱ ûȱ £ȱ
ȱ££¢ȱ¢ǰȱȱȱȱȱûȱȱǯȱ
22
Grundlegende Algorithmen mit Java
Aufgaben
ŗǯ
ȱ ȱ ȱ ȱ ǵȱ §ȱ ȱ ȱ ȱ ȱ
ȱǯȱ
Řǯ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱȱǰȱȱȱȱȱȱŘřŘŘȱȱŜśŚȱ£ȱǯȱ
řǯ ȱ ǰȱ ȱ £ ȱ ûȱ ȱ £ ȱ £ȱ
ǯȱ
Śǯ ȱ ȱ ȱ ǰȱ ȱ £ȱ ȱ ȱ ȱ
¡ȱȱȱ£ȱǯȱȱ ¡§ȱȱǵȱ
śǯ ȱȱȱȱȱûȱȱ£ȱȱȱ§ȱǯȱ
ȱ ¡§ȱ ȱȱǵȱȱȱȱǰȱȱ
ȱ§ȱȱǵȱ
Ŝǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢ǻǼȱ ȱ ȱ
ǯǯȱȱǯǯ¢ȱȱȱ Ȭ Ȭȱȱȱ
ȱȱȱǰȱȱȱȱ ǯȱ
ŝǯ ȱȱȱǰȱȱȱȱ £ȱȱȱǵȱ
Şǯ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ £ǯȱ
DZȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ
ȱȱȱȱǯȱ
şǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǵȱȱ
ŗŖǯ ȱȱȱ §ȱȱ ȱȱȱǵȱ
ŗŗǯ ȱȱ£ȱȱǵȱ
ŗŘǯ ȱȱȱȱȱ ȱ£ ǯȱȱ¢ȱȱǵȱ
ŗřǯ ȱ ȱ ȱ ȱ ȱ ǵȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱ
ŗŚǯ ȱ ȱ ȱ ¡§ȱ ȱ ǵȱ ȱ ȱ ȱ ȱ
̋ǰȱȱơ̇̄ȱǯȱȱ
ŗśǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ ǵȱ
ȱȱȱûȱȬ§ȱǯȱȱ
ŗŜǯ ȱ ȱ ȱ Ȭǯȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ȱȱȱȱ ȱȬ§ȱǵȱ
ŗŝǯ ȱȱȱ ȱȱȬȱǵȱ
ŗŞǯ ȱȱȱ ȱǵȱ
ȱȱȱȱȱȱȱȱǯȱŘȱ∈ǻřǼȱȱȱȱȱȱǯȱřȱ∈ǻŘǼȱȱȱȱȱǯȱŘƸŗȱ∈ȱǻŘǼȱȱȱȱǯȱǻƸŗǼǷȱ∈ȱǻǷǼȱ
ŗşǯ §ǯȱȱȱȱ ǰȱȱ§ȱȱȱ
£ȱ £ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ £ȱ §ȱ
£ȱûǯȱȱȱûȱȱ§ȱȱŚȱȱDZȱ
1 Algorithmen – grundlegende Konzepte
§
ȱ
ȱ
§ȱȱȱȱ DZȱ
ȱ
ȱ
ȱ
ȱ
23
24
Grundlegende Algorithmen mit Java
ŘŖǯ ȱȱȱ ¡§ȱȱȱDZȱ
ȱ
ȱȱȱ←ȱŗǰȱȱȱ¡ȱ
ȱȱȱ←ȱŗǰȱȱȱ¡ȱ
ȱȱȱ←ȱŗǰȱśȱ¡ȱ
ȱȱȱ←ȱŗǰȱƸŗȱ¡ȱ
ȱȱȱǿȱȀȱ
ȱȱȱǿȱȀȱ
ȱȱȱ←ȱŗǰȱȱȱ¡ȱ
ȱȱȱ←ȱŗǰȱȱȱ¡ȱ
ȱȱȱ←ȱŗǰȱŜȱ¡ȱ
ȱȱȱ←ȱŗǰȱȱ¡ȱ
ȱȱȱȱ←ȱŗǰȱȱ¡ȱȱȱ
ȱȱȱȱȱ←ȱŗǰȱȱ¡ȱ
ȱȱȱȱǿȱȱȱȀȱ
ȱȱȱȱȱȱȱǿȱȱȱȀȱ
ȱ
ȱȱǰȱ§ȱ
ȱ
Verschachtelte Schachteln
2
ȱ
ȱ
ȱȱ ȱȱ ȱȱȱȱ¢ȱȱ
ǯȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ
ȱȱ ȱȱãǰȱȱȱȱ£ȱȱûǯȱȱȬ
ȱ ȱ ȱ Ȭǰȱ ȱ đȱ £ûȱ ȬȦȬȱ
¢ȱ ǯȱ
Problembeschreibung
ȱ ȱ ȱ Ȭȱ ǯȱ
ȱ ȱ £ ȱ ȱ ǰȱ ȱ
ȱȱǻŘǰȱřǼȱȱȱȱȱ§ȱřȱȱ
ȱ ȱ Řȱ §ǯȱ ȱ ȱ Ȭ
ȱȱȱȱȱǻŚǰȱŞǰȱşǼȱȱȱ
ȱ §ȱ Śǰȱ ȱ ȱ Şȱ ȱ ȱ ãȱ şȱ §Ȭ
ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ £Ȭ
ǰȱȱ ȱãȱȱǯȱȱȬ
ǰȱ ȱ ȱ ȱ ȱ ƽȱ ǻŗǰȱ Řǰȱ ǯǯǯǰȱ Ǽȱ ȱ ȱ
ȱ ȱ ƽȱ ǻŗǰȱ Řǰȱ ǯǯǯǰȱ Ǽȱ ǰȱ ȱ ȱ ȱ
ȱ πȱ ȱ ǿŗǰȱ Řǰȱ dzǰȱ Ȁȱ ǰȱ ȱ ȱ
aπ (i ) < bi ȱ ûȱ ȱ ȱ ∈ȱ ǿŗǰȱ Řǰȱ ǯǯǯǰȱ Ȁǯȱ ȱ đǰȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ §ȱ ǯȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ǰȱ ȱ
ȱǯȱȱȱŗǰȱŘǰȱǯǯǯǰȱȱȱȱȱȱǰȱ ȱȱ
ȱȱȱȱȱƸŗȱǻŗȱ≤ȱȱǀȱǼȱǯȱȱ
ȱȱȱȱȱȱƽȱǻŘǰȱŜǼȱȱȱȱȱƽȱǻŝǰȱřǼǰȱ ȱȱȬ
ȱȱȱȱ ȱãȱ£ȱȱƽȱǻŜǰȱŘǼȱȱȱȱȱȱ
ȱȱȱȱȱǯȱȱȱȱƽȱǻşǰȱśǰȱŝǰȱřǼȱȱȱȱȱ
ȱ ȱ ƽȱ ǻŘǰȱ ŗŖǰȱ Ŝǰȱ ŞǼǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ûǯȱȱȱȱȱƽȱǻşǰȱśǰȱŝǰȱŗǼȱȱȱȱȱǰȱ ȱȱȬ
ȱ£ȱǻŗǰȱşǰȱśǰȱŝǼȱȱ ȱãȱȱȱȱȱȱȱȱ
ȱȱǯȱ
DZȱ ȱȱȱǯȱȱȱȱȱȱǯȱ ȱȱȱ
ȱȱǰȱȱȱ£ȱȱȱȱȱȱȱȱǯȱ
ȱȱȱȱȱȱȱȱȱȱ ȱǯȱȱ
26
Grundlegende Algorithmen mit Java
DZȱȱǰȱ ȱûȱȱ¡ȱȱȱȱǰȱȱȬ
ȱǯȱûȱȱ ǰȱȱȱȱȱ¡ȱȱǰȱ ȱ
ȱȱȱȱǰȱ ȱȱǯȱ£ȱȱǯȱȱ¡ȱ£Ȭ
£ȱ §ȱȱȱȱŘśŖǰȱȱȱȱŗǯȱȱ¡ȱ£ȱ
ȱȱȱȱ£ȱȱřŖŖǯȱȱȱǰȱȱȱȱȱ
Ƿȱ
DZȱ
ȱ
schachteln.in
schachteln.out
5 2
Laenge: 4
-------------3 7
3 1 4 5
8 10
*******************************
5 2
12 7
Laenge: 4
21 18
8 6
-------------7 2 5 8
5 2 20 1 30 10
*******************************
23 15 7 9 11 3
40 50 34 24 14 4
Laenge: 5
9 10 11 12 13 14
-------------31 4 18 8 27 17
5 4 2 7 9
44 32 13 19 41 19
*******************************
1 2 3 4 5 6
80 37 47 18 21 9
9 5
7 14 2 1 3
49 80 15 50 10
90 53 17 60 11
4 3 2 15 10
1 2 3 4 5
6 7 8 9 10
89 53 17 60 11
3 2 1 14 9
92 54 65 19 15
ǻȱ ȱȱȱŗşşŖǰȱȱǯȱȱ¡Ǽȱ
Problemanalyse und Entwurf der Lösung
£ȱŗǯȱ ȱȱȱȬȱȱȱƽȱǻŗǰȱŘǰȱdzǰȱȬŗǰȱǼȱȱȱƽȱǻŗǰȱ
ŘǰȱdzǰȱȬŗǰȱǼȱȱȱȱȱ ≤ȱƸŗǰȱȱ ≤ȱƸŗȱûȱȱȱȱŗȱȱȬŗȱǻȱȬ
ȱ ȱ ȱ Ǽǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱǰȱ ȱȱǀȱȱûȱȱ∈ǿŗǰȱŘǰǯǯǯǰȱȀǯȱ
ǯȱȱ£ȱȱ ȱȱǯȱȱȱȱǰȱȱȱȱȱ
ȱȱȱȱ∈ǿŗǰȱŘǰǯǯǯǰȱȀȱǰȱȱȱ ȱ≥ȱ ȱǯȱ ȱȱȱȱ ȱȱ
2 Verschachtelte Schachteln
27
ȱDZȱȱǀȱȱûȱȱ∈ǿŗǰȱŘǰǯǯǯǰȱȬŗȀȱȱȱ≥ȱȱǯȱȱȱȱȱ
ȱǰȱǰȱȱȱȱ≥ȱȱȱûȱȱ∈ǿƸŗǰȱǯǯǯǰȱȀȱǯȱȱ£ȱãǰȱȱ
ȱȱȱȱȱȱ<ȱȱȱûȱ ǰȱȱȱȱȱȱȱȱȱ
ȱǿŗǰȱŘǰȱdzǰȱȬŗȀǯȱȱȱȱ£ȱ ȱȱǯȱ ȱȱȱȱ
ȱȱȱȱȱȱȱ≥ȱǰȱȱȱȱȱȱǯȱǷȱ ȱȱȬ
ȱȱȱȱ ȱȱȱ ǯȱ÷ȱ
ȱ
ȱȱȱ£ȱ ȱȱȱȱȱȱȱȱ
ȱȱûȱȱǯȱȱ£ ȱȱȱȱ¡ȱȬ
ȱȱǰȱȱȱȱȱûȱǯȱȱȱ
ȱȱȱȱǰȱȱȱ ȱǻȱȱǷǼǰȱȱȱȱȱȱ
ȱȱȱȱǻȱȱȱȱȱȱȱȱȱȱȱ
ȱãđȱȱǰȱȱȱȱȱãǷǼǯȱȱȱȬ
ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ
ǯȱ ȱ ȱ Ǯ≤ȃȱ ȱ £ȱ £ȱ Ǯȃǯȱ ûȱ ȱ ȱ £ȱ
ȱȱȱ ȱȱȱȱûDZȱ
ȱ
ŗǯȱȱȱȱȱ
ûȱȱȱ
3 7
8 10
5 2
12 7
21 18
3 7
8 10
2 5
7 12
18 21
Řǯȱ¡ȱȱȱȱ
ȱȱȱûȱȱȱ
3 7
8 10
2 5
7 12
18 21
2 5
(3)
3 7
(1)
7 12 (4)
8 10 (2)
18 21 (5)
ȱ
ȱȱȱ§ȱȱȱȱȱȱȱȱ
¢ȱ ȱ ȱ ȱ ȱ ȱ ȱ Şȱ ǯȱ ȱ ¡ȱ
ȱȱȱȱ£ȱǮȄȱȱǻŘǰȱśǼȱ→ȱǻřǰȱŝǼȱ→ȱǻŝǰȱŗŘǼȱ→ȱǻŗŞǰȱŘŗǼǰȱ
ȱȱȱȱ£ȱȱȱ§ȱŚǯȱȱȱȱûȱȱ
ȱȱǻřȱŗȱŚȱśǼȱȱȱǯȱ
Der Algorithmus
ȱȱȱȱŗǰȱȱŘǰȱǯǯǯǯǰȱȱȱ¢ȱǰȱȱȱȱȱ
ûȱ ȱ ǯȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ£ȱȱǯȱûȱȱ ȱ£ ȱȱǽǾȱȱǽǾǯȱȱ§Ȭ
ȱ ȱ ȱ ȱ ǽǾȱ ȱ ȱ ¡ȱ ȱ £ȱ ȱ ȱ ǽǾȱ ǻǽǾƽȬŗǰȱ
ȱǽǾƽŗǼǯȱDZȱ
ȱ
28
Grundlegende Algorithmen mit Java
-
ȱ
-
ǽǾȱȱȱ¡ȱ§ȱȱǰȱȱȱȬ
ǰȱȱ£ȱȱȱǯȱȱȱ DZȱ
ǽŗǾȱ←ȱŗȱǻȱȱȱȱȱȱǰȱȱȱȬ
ȱȱȱȱǼǰȱ
ǽǾȱ←ȱŗȱƸȱ¡ǿǽǾȱǀȱȱȱȱȱ ȱ ȱȱȀȱǻȱȱȱ£ȱȱȱ
Ǽǯȱ
ǽǾȱ ȱ ȱ ¡ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
§ȱ ȱ ȱ ¡ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱǻ ȱȱȱȱ§ȱǰȱȱȱȱȱȬŗǼDZȱ
ǽŗǾȱ←ȱȬŗȱȱǻȱȱȱȱȱ§Ǽǰȱ
ǽǾȱ←ȱǰȱǽǾȱ¡ȱȱǻǀȱȱȱȱȱǼǯȱ
ȱȱȱȱȱ¡ȱ§ȱǰȱȱȱ ȱȱǯȱ
ȱ
ȱȱǽǾȱȱǽǾȱ ȱ£ȱûǯȱȱ£ȱȱȱȬ
ȱ¡ȱ£ȱȱȱȱȱ ¡ǯȱȱȱ§ȱǽǾȱûȱȱ
ȱȱãđȱȱȱȱǽ¡Ǿȱǰȱȱ ȱ¡ȱȱȱǯȱ
ȱãȱ ȱȱȱȱȱǯȱ
ȱ
ȏ ȏ ȱ
ȱ
ŗǯ ȱ¡ȱŗǰȱŘǰȱǯǯǯȱȱ
ȱ
Řǯ ȱǻȱ←ȱŗǰȱDzȱȱŗǼȱ¡ȱ
ȱ
ȏǻǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
řǯ ȏ¡¢ǻŗǰȱŘǰȱǯǯǯǰȱǼȱ
ȱ
Śǯ ǽŗǾȱ←ȱŗǰȱǽŗǾȱ←ȱȬŗǰȱ¡ȱ←ȱŗȱ
ȱ
śǯ ȱǻȱ←ȱŘǰȱDzȱȱŗǼȱ¡ȱ
ȱ
ȱśǯŗǯȱǽǾȱ←ȱŗǰȱǽǾȱ←ȱȬŗȱȱ
ȱ
ȱśǯŘǯȱȱǻȱ←ȱŗǰȱȬŗDzȱȱŗǼȱ¡ȱ
ȱ
ȱ
ȱȱ ȱǻȱȱȱȱȱǽǾƸŗȱǁȱǽǾǼȱȱ
ȱ
ȱ
ȱ
ǽǾȱ←ȱǽǾƸŗȱ
ȱ
ȱ
ȱ
ǽǾȱ←ȱȱ
ȱ
ȱ
ȱȱȏ ȱ
ȱ
ȱȱȱȱȱȱȱȱȏȱ
ȱ
śǯřǯ ȱǻǽǾȱǁȱǽ¡ǾǼȱȱȱ
ȱ
ȱȱ¡ȱ←ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱ ȱȱȱȱȱȱȱȱȱȏ ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱŜǯȱ¡ȱǻǽŗǯǯǾǰȱǽǾǰȱ¡Ǽȱ
ȱ
ȏ ȏ ȏ ȱ
ȱ
2 Verschachtelte Schachteln
ȱ
¡§ȱ ȱ ȱ ȱ O (n 2 m + nm log m) ǰȱ
29
ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱȱȱǻȱȱŘȱȱ O(nm log m) ǰȱ
ȱȱȱȱDzȱȱȱśȱȱǻŘǼǰȱ ȱȱ£ ȱȱȬ
ȱȱȱ§ȱȱDzȱȱȱ£ ȱȬȱȱûȱȱȬȱ
ǻǼǼǯȱȱ
ȱ
ȱ ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱǽǾȱȱȱȱ ¡ȱ¡ȱDZȱ
ȱ
ȏȱǻǽŗǯǯǾǰȱǽǾǰȱ¡Ǽȱ
ȱ
ȱȱȱȱȱDzȱ
ȱ
ȱȱȱȱ ¡ȱƜȱ¡ȱ
ȱ
ȱȱȱȱȱǻȱ
¡ȱǁƽȱŖȱǼȱȱ
ȱ
ȱȱȱȱȱȱȱǯȱǻȏǻǽ
¡ǾǼǼDzȱ
ȱ
ȱȱȱȱȱȱȱ ¡ȱƜȱǽ ¡Ǿȱ
ȱ
ȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱ
ȱ
ȏ ȏȱȱǻǽŗǯǯǾǰȱǽǾǰȱǼȱ
ȱ
ȱ
ȱ ¡§ȱȱȱȱȱǻǼǯȱȱ
Das Programm
ȱ ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ
ȱ ¡ǰȱ ȱ ȱ ȱ ¡ȱ ǻȱ ûȱ ȱ ȱ ȱ Ǽȱ
ȱȱ¢ȱȱǯȱȱȱ ¡ǻǼǰȱǻǼȱȱ ǻǼȱ
ȱȱȱȱȱ¢ȱ¡ǯȱ
ȱ
import java.io.*;
import java.util.*;
public class P01_BoxInBox {
private static class Box implements Comparable<Box> {
private int dimensions[];
private int index;
public Box(int boxIndex, int boxDimensions[]) {
this.index = boxIndex;
this.dimensions = boxDimensions;
}
30
Grundlegende Algorithmen mit Java
public int compareTo(Box otherBox) {
assert
this.dimensions.length == otherBox.dimensions.length :
" Schachteldimensionen sind nicht einheitlich!";
int rt = 0;
for (int i = 0;
i < this.dimensions.length && rt == 0; i++) {
rt = this.dimensions[i] - otherBox.dimensions[i];
}
return rt;
}
public int getIndex() {
return index;
}
public boolean fitIn(Box otherBox) {
assert
this.dimensions.length == otherBox.dimensions.length :
" Schachteldimensionen sind nicht einheitlich!";
boolean fit = true;
for (int i = 0; fit && i < this.dimensions.length; i++) {
fit = this.dimensions[i] < otherBox.dimensions[i];
}
return fit;
}
}
public static void main(String args[]) {
Scanner scanner = null;
PrintWriter out = null;
try {
scanner = new Scanner(new File("schachteln.in"));
out = new PrintWriter(new File("schachteln.out"));
while (scanner.hasNextInt()) {
Box boxes[] = new Box[scanner.nextInt()];
int numDimensions = scanner.nextInt();
for (int i = 0; i < boxes.length; i++) {
int boxDimensions[] = new int[numDimensions];
for (int j = 0; j < numDimensions; j++) {
boxDimensions[j] = scanner.nextInt();
}
Arrays.sort(boxDimensions);
boxes[i] = new Box(i, boxDimensions);
}
Arrays.sort(boxes);
2 Verschachtelte Schachteln
int v[] = new int[boxes.length];
Arrays.fill(v, 1);
int vPred[] = new int[boxes.length];
Arrays.fill(vPred, -1);
int indexMax = 0;
for (int i = 1; i < boxes.length; i++) {
Box currBox = boxes[i];
for (int j = 0; j < i; j++) {
if (boxes[j].fitIn(currBox) && v[j] + 1 > v[i]) {
v[i] = v[j] + 1;
vPred[i] = j;
}
}
if (v[i] > v[indexMax]) {
indexMax = i;
}
}
out.print("Laenge: ");
out.println(v[indexMax]);
StringBuilder bf = new StringBuilder();
for (int currIdx = indexMax; currIdx >= 0;
currIdx = vPred[currIdx]) {
bf.insert(0, ' ').insert(0,
(boxes[currIdx].getIndex() + 1));
}
out.println(bf);
out.println("*******************************");
}
} catch (Throwable th) {
th.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
31
32
Grundlegende Algorithmen mit Java
Die Programmanalyse
ǯȱ ȱ ȱ ¢ȱ ¡ȱ ȱ ȱ Ȭȱ ȱ £ȱ
ȱȱȱȱǯȱȱȱȱ§ȱȱȱ ȱ
£ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǻ £Ǽȱ DZȱ ȱ
ȱȱȱȱ£ȱȱȱ ȱȱȱȱ ȱȱȱȬ
ǯȱȱȱ ȱȱ ¡ȱȱȱȱȱȱãȬ
ǯȱȱ
ȱ
ǯȱ ȱ ȱȱȱ ȱȱȱȱû ȱȱ§ȱ
ȱȱ ȱȱ ǰȱȱȱǯȱ ȱ ȱȬ
ȱûǰȱ ȱȱȱȱ ȱȱ ǰȱûȱȱȬ
ȱ£ȱȱȱȱȱãȱûȱ ǯȱȱ ȱ ȱ
ȱ ȱ ȱ£ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ £ ȱ £ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱȱȱ £ȱDZȱ
ȱ
public Box(int boxIndex, int boxDimensions[]) {
this.index = boxIndex;
this.dimensions = boxDimensions;
}
ȱ
ȱ£ȱ ȱȱȱǻǼȬȱȱȱȱ¢ȱ¡DZȱ
ȱ
boxes[i] = new Box(i, boxDimensions);
ȱ
ȱûȱȱ ȱ ȱ ȱ¡ǰȱ£ȱȱȱȬ
ȱȱȬ ȱȱǰȱȱ ȱȱȱȬ
ȱ ȱȱȱǯȱ ȱȱ ȱȱ ȱȱ
ȱ ǰȱ£ȱȱȱȱȬ ǯȱ
ȱ
¢ǯȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ DZȱ Ǯȱ ȱ ȃǯȱ ¢ȱ ȱ ȱ ǰȱ ȱ
ȱ ȱ ȱ ȱ ȱ ûǯȱ ȱ ȱ ȱ Ȭ
ȱ ȱ Ȭȱ ǻûȱ ǰȱ ǯȱ Ǽȱ
ȱ ȱ ȱ §ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ
û¢ȱ ǻûȱ ǰȱ ǯȱ Ǽǯȱ ȱ ȱ ȱ Ȭ
ȱ ȱȱûȱȱǯǯ¢ǯǻǼǰȱȱȱȱȬ
ȱȱ¢ȱǽǾȱȱȱȱȱȱȱ¢ȱ¡ǽǾǯȱ
ȱ
2 Verschachtelte Schachteln
33
ȱȱȱ ȱ¡ǯȱȱ ȱ¡ȱȱȱȱȱ ȱǻǯȱȱ
ȱǼȱȱŖŗȏ¡ ¡ǯȱȱȱȱȱȱȱǰȱ ȱȱȱ
ȱȱȱ£ȱ ȱȱȱȱȱȱ £ȱ
ǯȱȱ ȱ¡ȱȱǰȱ ȱȱȱȱǰȱȱȱđȱ£ȱ£Ȭ
ǯȱ
ȱ
ȱ ȱǯǯǯȱ ǰȱȱȱȱǰȱãȱȬ
ȱȱ ȱȱȱȱ ȱ£ǰȱ£ȱȱȱ
ǯȱȱ ȱȱȱû ȱȱȱȱȱȬ
ȱ ǰȱȱȱ ȱ ȱ £ȱãǰȱȱȱȱ ȱ
ȱǯȱȱ ȱȱ ȱ§ȱȱȱ£ȱȱȱ
ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ ȱ DZȱ ǯǯǰȱ Ȭ
ǯǯǰȱ ǯǯǰȱ ǯǯ£ǰȱ ǯǯǰȱ Ȭ
ǯǯ ǰȱǯǯǰȱǯǯǰȱǯǯǯȱȱãǰȱȱ
ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ǻǽǾȱ Ǽȱ
ȱȱ ȱ¢ȱǰȱȱȱȱȱǯȱDZȱȱ
ȱ
Arrays.sort(boxes);
ȱ
ûȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ Ȭ
DZȱ
ȱ
public int compareTo(Object o)
ȱ
ȱ ȱȱȱȱȱǻǼǰȱȱȱȱ £ȱȱ
ȱ ȱ Ǯûȱ ȃȱ ǰȱ ȱ ȱ ȱ ȱ £ǯȱ ǯȱ ȱ Ȭ
ȱȱ ȱãǯȱǻǼȱȱ
ȱǀȱŖǰȱ ȱȱȱȱȱȱ£ȱȱǰȱ
ȱȱȱȱŖǰȱ ȱȱȱȱȱȱ£ȱȱȱȱȱ
ȱǁȱŖǰȱ ȱȱȱȱȱȱ£ȱȱǰȱ
£ûǯȱ
ȱ
ȱȱȱȱǰȱ ȱȱȱ¢ǯǻǽǾȱǼȱȱȱȬ
¢ȱȱǯȱ
ȱ
ȱ ȱǯǯ¢ȱȱǰȱȱ¢ȱȱȱ¢ȱ
ȱȱǰȱǰȱǰȱǰȱǰȱûȱȱȱ
ãđȱǯȱǯǯ¢ȱȱȱȱȱǻǼǰȱȱȱ¢ȱȱ
ȱ§ǯȱȱ ȱȱȱ¡ǰȱ ȱȱ££Ȭ
34
Grundlegende Algorithmen mit Java
ȱ£ȱȱǯȱȱ ȱȱȱȱȱȱ¢ǯǻǼȱ
ȱ¢ǯǻǼǯȱ
ȱ
ȱȱȱȱ ȱȱȱ¢ȬȬ ǯȱȱȱȱȱ
DZȱȱ
ȱ
try {
Anweisung;
…
}
catch (Ausnahmetyp_1 x1) {
Anweisung;
…
}
catch (Ausnahmetyp_2 x2) {
Anweisung;
…
}
…
catch (Ausnahmetyp_n xn) {
Anweisung;
…
}
[
finally {
…
}
]
ȱ
ȱ ǰȱȱȱȱ¢Ȭȱǰȱãȱȱȱûȱ£ȱȬ
ȱȱȱ¢ȱ¢ȏȱûǯȱȱȱǰȱ ȱȱȱ
ȱȱȱȱȱȱȱȱȬȱ ûǰȱȱ
ȱȱȱȱȱ ¢ȱ§ǯȱȱȱ
ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǻǼȱ ǰȱ ȱ ȱ £ȱ ȱ Ȭ
£ȱ £ûǯȱ ȱ ¢Ȭ ȱ ȱ ȱ ¢ȬȬ ȱ ȱ ǯȱ ȱ
ȱ ȱ ûȱ ǻȱ Ǽǰȱ ȱ ȱ ȱ ȱ ¢Ȭȱ ǰȱ ȱ
ȱ ȱȱ Ȭȱȱȱȱǰȱ ȱȱȱ§ȱûǰȱ
§ȱ £ȱ ǻ£ǯȱ ǯȱ ȱ £Ǽǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ ȱ ȱ Ȭȱ ȱ ȱ £ȱ
đǯȱȱ
ȱ
2 Verschachtelte Schachteln
35
ȱ ȱ ǯȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǯȱ ǰȱ ȱ ȱ ȱ śȱ ûȱ ǯȱ ȱ ȱ ȱ Ȭ
ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ
ǯȱ ȱ £ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ¢ȱ Ȭ
ȱȱȱ£ȱȱǯȱȱ ȱȱȱȬ
ǻǼȱȱǻǼǰȱȱȱ¢ȱ£DZȱǻǼȱûȱȱ ȱȱȬ
ȱȱȱȱȱ£ǰȱǻǼȱûȱȱȱȱȱȱ
ȱǯȱ
ȱ
ȱ ȱȱȱȱȱǯȱȱȱȱȱȱȱȬ
ȱǯȱȱȱ ȱȱ ȱśȱûǯȱȱȱȱ£ȱȱȱ
£ǯȱǯȱȱ§ȱ ȱǯǯǯȱȱ £ȱȱȱȱȱȱ
¡ǰȱȱȱ¢ȱȱȱȱǯȱȱûȱ Ȭ
DZȱ
• ȱ£ȱȱȬȱ ȱȱȬȬ ȱȱȬ
ǰȱ ȱȱȱDZȱ
ȱ
scanner = new Scanner(new File("schachteln.in"));
ȱ
ǻȱȱȱ£ ǰȱȱȱȱȱ £ȱ
ȱȱȱ¢ȬȬǼȱ
• ȱȱȱȱȱ¡ǻǼȱǰȱȱȱDZȱ
ȱ
Box boxes[] = new Box[scanner.nextInt()];
int numDimensions = scanner.nextInt();
for (int i = 0; i < boxes.length; i++) {
int boxDimensions[] = new int[numDimensions];
for (int j = 0; j < numDimensions; j++) {
boxDimensions[j] = scanner.nextInt();
}
…
ȱ
• ȱ¡£ȱȱȱȱȱ¢ȱȱȱȱȬ
¡ǻǼȱûǰȱȱȱDZȱ
ȱ
while (scanner.hasNextInt()) {
…
ȱ
ȱ ȱȱȱȱȱǯȱȱȱãǰȱȱȱȬ
¢ȱȱȱ¡ȱȱ£ǰȱȱ£ ȱDZȱ
• ȱ ǰȱ £ǯȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ Ȭ
ȱ£ǰȱȱȱȱȱȱ ȱDZȱ
36
Grundlegende Algorithmen mit Java
out = new PrintWriter(new File("schachteln.out"));ȱ
ȱ
•
ȱ ȱ ȱ ¢ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ǻǼȱ ûȱ ǰȱ ȱ ȱ ȱ ûȱ ȱ
ǻ¢Ǽȱȱǻ¢Ǽǯȱ ȱȱȱ ȱ
ȱȱDZȱ
ȱ
out.print("Laenge: ");
out.println(v[indexMax]);
StringBuilder bf = new StringBuilder();
…
out.println(bf);
out.println("*******************************");
ȱ
ȱȬ ȱȱȱȱ ȱŗǯŚǯȱȱȱȱ£ǰȱǰȱȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǰȱ £ȱ ûûǯȱ §đȱ Ȭ
ȱȱȱ ȱȱȱǻȱ ûȱȱ §Ȭ
§Ǽǯȱȱȱȱȱȱûȱ£ȱǰȱȱȱȱȱȱ ȱŗǯŚȱȱ
ȱȮȱŗǯŚȱǰȱȱ ȱŗǯśȱȮȱŗǯśȱȱȱ ȱŗǯŜȱȮȱŗǯŜǯȱ ȱȱȬ
£ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ǯȱ ȱ Ȭ
ȱ £ȱ ȱ ȱ ǰȱ ȱ ȱ û ȱ £ȱ ãȬ
ǯȱȱȱȱȱȬ ȱDZȱ
ȱ
assert Ausdruck1 [ : Ausdruck2 ];
ȱ
ȱ ȱ£ȱ£ȱûǰȱȱŗǰȱȱȱ¢ȱȱȱǰȱ ȱ
ǯȱȱǰȱûȱȱȱȱȬ ǰȱ ȱ ȱȱ
ȱ ȱ ¢ȱ ǯǯȱ ǯȱ ȱ ȱ ȱ Ȭ
Řȱ ȱ ¡ǰȱ ȱ ȱ ȱ ȱ ¡ǯȱ ȱ ȱ ȱ
Řǰȱȱ ȱȱ ȱȱ ȱȱȱûȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ǯȱ ȱ ¢ȱ ȱ
Řȱȱȱȱǰȱȱȱȱȱȱȱǰȱȱȱ
£ûǯȱȱ ȱȱȱȱȱȬ ȱȱȱȬ
ȱ ǻǼȱȱȱ ǻǼǰȱȱ£ȱ£ǰȱȱ£ ȱȱȱȬ
ȱDZȱ
ȱ
assert
this.dimensions.length == otherBox.dimensions.length :
" Schachteldimensionen sind nicht einheitlich!";
ȱ
2 Verschachtelte Schachteln
37
Aufgaben
ŗǯ
ȱ ȱ ¡ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱûȱȱǰȱȱȱȱȱȱȱǰȱȱȱ
ȱȱȱȱȱȱǯȱȱȱȱȱȱȱȬ
ǵȱ ǯȱ
Řǯ ȱȱȱȱȱȱȱǻǼǯȱȱ
řǯ ȱãȱǰȱȱȱȱȱȱȱǻȱǰȱ§ȱ
ȱȱ£ȱđȱȱȱ ǯǼǯȱ ȱȱȱȱ
ǰȱȱȱ ȱȱȱûȱ ǯȱ
Śǯ ȱȱȱǰȱȱȱđȱȱûȱȱ
ȱǰȱȱûȱȱȱȱǯȱȱȱȬ
ȱȱǰȱȱȱȱȱ§£ȱȱđȱȱȱ
§ȱȱȱȱȱȱǯȱ
śǯ ȱãȱǰȱȱȱȱȱȱȱȱȬ
ȱ ȱ ȱ ¡ȱ §ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱȱȱȱȱȱȱ ǯȱ
Ŝǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ǰȱȱȱȱãǰȱȱȱ£ȱȱȱ
ȱȱȱ£ȱǯȱ
ŝǯ ȱ ȱ ǰȱ ȱ ȱ ȏȏȱ £ȱ ¢Ȭ
ȱ ȱ ãǰȱ ȱ ȱ ȱ £ȱ ¢ǰȱ ȱ
ȱȬȬ ǯȱ
Şǯ ȱȱȱ ȱȱȱȱ ȱǯǯȱȱ
ȱ Ȭ Ȭǰȱȱȱȱȱ ȱȱ ȱ
ȱȱȱǻǼȱȱȱ ȱǻ ¢Ǽȱǯȱ
şǯ ȱ ȱ ȱ Ȭ Ȭȱ ûȱ ȱ ȱ ǯǯǰȱ
ǯǯǰȱ ǯǯǰȱ ǯǯ£ǰȱ ǯǯǰȱ
ǯǯ ǰȱ ǯǯǰȱ ǯǯȱ ȱ ǯǯȱ ǯȱ
ȱȱǰȱȱȱȱ ȱ£ǯȱ
ŗŖǯ ȱ ȱ ȱ ȱ ȱ ¢ȬȬ DZȱ ȱ ȱ
Ȭ ǰȱȱȬ ǰȱȱ¢Ȭ ȱȱǯȱȱȱ
ȱ ȱ ȱ ȱ ¢Ȭȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ Ȭãȱ ǯȱ ȱ ȱ ȱ £ȱ ȱ
ȱȱDZȱ¡ǰȱ ¡Ȭ
¡ǰȱ ¡ǰȱ ¢¡ǰȱ Ȭ
¡ǰȱ ¡ǰȱ ¢£¡ǰȱ Ȭ
¡ȱǻȱȱȱȱǯǼȱ
ŗŗǯ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ûȱ ¢Ȭ
ȱȱȱȱȱȱǯȱ DZȱȱ Ȭ
38
Grundlegende Algorithmen mit Java
ǰȱ ûȱ ǻǻǼǰȱ ǻǼǼǰȱ ãȱ ǻǻǼǰȱ ǻǼǼȱ ȱȱ
§ȱ ȱ ȱ ǻǻǼǰȱ ǻǼǼǰȱ ȱ ȱ §ȱ
ǻǻǼǰȱ¢ǻǼǼǰȱ ȱȱȱǯǯȱǻǻǼǼǯȱ£ȱ
ȱȱȱȱȱȱȱȱǯȱ
Anmerkungen
ȱȱȱ ȱȱȱ ȱȱȱDZȱ
ŗǯ ȱȱ¢ȱǯȱ
Řǯ ȱ £ȱ ȱǰȱ¢ǯȱ
řǯ ȱ £ȱȱȱȱ ǯȱ
Śǯ ȱ ȱǯǯǯȱ
śǯ ȱ ȱǯǯǯȱ
Ŝǯ ȱȱȱȱ ȱȱ¢ȬȬȱȱȬ ǯȱ
ŝǯ ȱȱȱ¢ȱȱȱȱȱȱȱȱȬ
ȱǯǯȱ
Şǯ ȱȱȱ¢ȱȱȱȱȱǯǯǯȱ
ȱ
ȱ ¢ȱȱǰȱȱ
ȱ
3
Greedy
ȱ
ȱ
ȱ
ȱ
ȱ
Grundlagenȱ
¢Ȭȱ ǻǯȱ ¢ȱ ƽȱ Ǽȱ ȱ ȱ £ǰȱ ȱ ȱ Ȭ
ȱȱȱȱȱ §ǯȱȱûȱȱȱȱ£ȱȬ
ûȱȱȱ ǰȱȱ£ȱ ȱȱȱ Ȭ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ãǯȱ ȱ đȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ ǯȱ ȱ ȱ
ȱȱǰȱ ȱȱȱȱȱûȱȱȱȬ
ǰȱ §ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱȱ ¢Ȭȱȱûȱȱȱȱãǰȱȱȱȱ
ãȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭȱ ǰȱ
ȱȱȱȱ ȱ§ǯȱȱȱȱȱȬ§ǰȱ
ȱ ȱ ȱ ¢Ȭȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ãȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ûȱ £ȱ ȱ
§ǰȱȱȱ§ȱȱȱȱ££ȱȱȱȬ
ǯȱȱ
ȱȱȱȱȱGreedyȬDZȱ
ȱ
ȱ
ȏ ¢ǻȱǼȱ
ŗȱȱȱȱȱ←ȱȱ
ȱ←ȱ∅ȱ
ȱȱǻȱȬǼȱȱ
ȱȱȱ¡ȱ←ȱȱȱ¢ȱȱȱȱŗȱ
ȱȱȱŗȱȱ←ȱŗȱȱǿ¡Ȁȱ
ȱȱȱ ȱǻȱ∪ȱǿ¡Ȁȱ¢ȱǼȱȱ
ȱȱȱȱȱȱȱȱȱ←ȱȱȱȱ∪ȱȱǿ¡Ȁȱ
ȱȱȱȏ ȱ
ȏȱ
ȏ ȏ ¢ǻȱǼ
40
Grundlegende Algorithmen mit Java
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ DZȱ ȱ ȱ
û£ȱ ȱ ȱ ȱ ǻDijkstraǼǰȱ ȱ ȱ ȱ ȱ
ǻPrim, KruskalǼǰȱȱȱǰȱ Ȭ ǯȱ
Problem 1. Rucksackproblem
ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱȱȱȱȱȱȱ £§ȱȱȱȱ
ȱȱȱȱ£ ǯȱ ǯȱȱȱ
ȱãǰȱȱȱȱȱȱ£ȱûǰȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ãȱ ǻȱ ǮȬ
ȃǼȱȱȱȱȱȱȱȱǯȱDZȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
£§ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ǻ ǰȱǼȱûȱȱǰȱȱȱȱǯȱDZȱȱȱȱȱȬ
ȱǯȱȱ£ ǯȱȱȱûȱȱǰȱ ȱȱDZȱ
ȱ
rucksack.in
rucksack.out
41
Objekt 2: 23.45 600.54 - vollstaendig
12.34 123.99
Objekt 1: 12.34 123.99 - vollstaendig
23.45 600.54
Objekt 3: 12.78 90.67 - 5.21kg
12.78 90.67
9.34 45.32
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ȱ §ȱ Ȧ ȱ ȱ ȱ Ȭ
ȱȱȱȱȱȱȱǯȱȱ£ȱȱ ȱȱ
ȱ ȱȱȱȱ ǯȱȱȱȱ ȱǰȱȱ
ȱ ȱ ûȱ ȱ ȱ DZȱ ȱ ǻ Ǽǰȱ ȱ ǻǼȱ ȱ Ȭ
¡ȱ ǻ¡Ǽȱ ȱ ȱ ȱ ȱ ûȱ ǯȱ ȱ ȱ ȱ
ȱ ȱ ȱ ûȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǻǼȱ ȱ ǻǼǯȱ ȱ ãǰȱ ȱ ȱ ȱ Ȭ
ȱ ȱ£ȱǰȱȱȱȱǻǼȱȱȱ ȱȱǰȱ
ȱȱȱȱǯȱDZȱȱ
ȱ
Collections.sort(v);
ȱ
ûȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ Ȭ
DZȱ
public int compareTo(Object o)
3
Greedy
41
ȱ
ȱ ȱȱȱȱȱǻǼǰȱȱȱȱ £ȱȱ
ȱ ȱ Ǯûȱ ȃȱ ǰȱ ȱ ȱ ȱ ȱ £ǯȱ ǯȱ ȱ Ȭ
ȱȱ ȱãǯȱǻǼȱȱ
ȱǀȱŖǰȱ ȱȱȱȱȱȱ£ȱȱǰȱ
ȱȱȱȱŖǰȱ ȱȱȱȱȱȱ£ȱȱȱȱȱ
ȱǁȱŖǰȱ ȱȱȱȱȱȱ£ȱȱǰȱ
£ûǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
§ȱ Ȧ ǯȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱȱ£ȱȱǯȱȱȱ£ȱȱȱȱǰȱȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ £ȱ ȱ ȱȱ
ǻȱ≤ȱŖȱǰȱȱȱȱȱǼǯȱȱ ¡§ȱȱȬ
ȱȱǻȱȱǼǰȱ ȱȱȱȱȱǻǼȱ§ȱǯȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ
ȱDZȱ
ȱ
out.print(v.get(i));ȱ
ȱ
ȱ ȱȱȱǻǼȱȱȱ ȱȱȱȬ
ǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P01Rucksack {
private static final String FileInputName = "rucksack.in";
private static final String FileOutputName = "rucksack.out";
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(
new File(FileInputName)).useLocale(Locale.ENGLISH);
out = new PrintStream(new File(FileOutputName));
float M = scanner.nextFloat();
List<RucksackObject> v = new ArrayList<RucksackObject>();
int index = 0;
42
Grundlegende Algorithmen mit Java
while (scanner.hasNextFloat()) {
float weight = scanner.nextFloat();
if (!scanner.hasNextFloat())
break;
float value = scanner.nextFloat();
v.add(new RucksackObject(++index, weight, value));
}
Collections.sort(v);
int i = v.size() - 1;
while (i >= 0 && M > 0) {
float wgt = v.get(i).getWeight();
if (M >= wgt) {
M -= wgt;
--i;
} else {
M = -M;
}
}
for (int j = v.size() - 1; j > i; --j) {
out.print(v.get(j));
out.println(" - vollstaendig");
}
if (i >= 0 && M < 0) {
out.print(v.get(i));
out.print(" - ");
out.print(-M);
out.print(" kg");
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
class RucksackObject implements Comparable<RucksackObject> {
private int index;
private float weight, value;
RucksackObject(int index, float weight, float value) {
this.index = index;
this.weight = weight;
this.value = value;
3
Greedy
43
}
public int compareTo(RucksackObject other) {
float diff = this.value / this.weight –
other.value / other.weight;
return diff > 0f ? 1 : (diff < 0f ? -1 : 0);
}
public String toString() {
return "Objekt " + this.index + ": " +
this.weight + " " + this.value;
}
public float getWeight() {
return weight;
}
}
Aufgaben
ŗǯ
ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ
ȱȱȱȱȱǯȱǰȱȱȱȱȱȱ
ȱ
public int compare(Object o1, Object o2)
ȱ
Řǯ
ǯȱȱȱȱȱȱǯȱȱ
ȱ ȱ ȱ ãȱ ȱ ȱ §ȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ¢Ȭȱ
ȱȱȱȱãǯȱȱȱȱȱûǯȱȱ
Problem 2. Kartenfärbung
ȱȱȱ£ȱȱǻŘȱ≤ȱȱ≤ȱŘŖǼȱȱ§ȱȱȱ£ãȱȱȱ
¡ȱǽǾǽǾȱǰȱȱȱǽǾǽǾȱƽȱŗȱǰȱ ȱȱ§ȱȱȱȱȱǰȱȬ
ȱ ȱ ǽǾǽǾȱ ƽȱ Ŗǯȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ ȱ
£ȱ ȱ ȱ £§ǰȱ ȱ £ ȱ §ǰȱ ȱ ȱ £ǰȱ
ȱȱȱûǯȱ ȱȱȱȱȱȱȱ
£ ȱȱûȱȱŗȱȱȱȱǯȱDZȱ
ȱ
map.in
colors.out
7
1 2 3 4 1 2 5
0 1 1 1 0 0 1
1 0 1 1 0 0 0
1 1 0 1 1 0 1
44
Grundlegende Algorithmen mit Java
1 1 1 0 1 0 1
0 0 1 1 0 1 1
0 0 0 0 1 0 1
1 0 1 1 1 1 0
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ Ȭǰȱ ȱ ȱ
ȱ ȱ ¡ȱ ¡§ǯȱ ȱ ¢Ȭȱ ȱ £ ȱ ȱ
£ȱ£ȱȱǰȱȱȱȱȱȱ£ǯȱȱ§ȱȱ
ȱ ȱ ȱ Ŗȱ ȱ ȱ £ȱ ȱ §ȱ ȱ ȱ ȱ ûȱ ȱ
ǻȱȱȱȱ§ȱǼȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P02MapColoring {
private static final String FileInputName = "map.in";
private static final String FileOutputName = "colors.out";
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
int n = scanner.nextInt();
int a[][] = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
a[i][j] = scanner.nextInt();
}
}
int col[] = new int[n];
col[0] = 0;
for (int i = 1; i < n; i++) {
- col[0] ← 0
int j = -1;
- ȱ ȱȱȱȱûȱȱ
boolean ok = false;
ûȱ ȱ ȱ ȱ ǻ ȱ ȱ ȱ ǮȄȱ ȱ
do {
ȱȱ ¡ȱȱȱȱǰȱȱ
j++;
1==a[k][i] && col[k]==jȱ ǰȱ ȱ §ȱ ok
ok = true;
ȱ
false)ȱ
for (int k = 0;
ok && k < i; k++)
if (1 == a[k][i] && col[k] == j)
3
Greedy
45
ok = false;
} while (!ok);
col[i] = j;
}
out = new PrintStream(new File(FileOutputName));
for (int i = 0; i < n; i++) {
out.print(col[i] + 1);
out.print(" ");
}
} finally {
if (scanner != null) scanner.close();
if (out != null) out.close();
}
}
}
ȱ
Aufgabe
ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ £ãȱȱȱȱ
ǰȱ ȱ ȱ ȱ ȱ §ȱ ȱ Śȱ ǯȱ ȱ ȱ ȱ ȱ
ȱȱ§ȱǰȱȱ£ ȱ§ȱȱȱȱȱ ǯȱ
Problem 3. Springer auf dem Schachbrett
ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ȱ
)ȬȱǻŚȱ≤ȱǰȱȱ≤ȱŗŖŖǼȱȱȱǰȱȱȱȱȱ
ȱȱȱǯȱDZȱ ȱȱȱǯȱȱ
ȱȱȱȱȱȱ ãđȱǰȱȱȱȱȱ£ ȱ
ȱ ȱ ȱ ǻ ǰȱ Ǽȱ ȱ ǯȱ DZȱ
ȱȱȱȱȱǯȱȱȱǰȱ ȱ
ȱ ȱ ȱ ¡ȱ ȱ ǰȱ ȱ ȱ ȱ ŗȱ ȱ ȱ ȱ
ȱûȱȱŗȱ£§ȱ ǯȱȱȱãȱȱ ǰȱȱȱ
ȱǮ ȱǷȃȱǯȱDZȱ
ȱ
springer.in
springer.out
5 5
19
12
7
2
21
2 2
6
1
20
17
8
11
18
13
22
3
14
5
24
9
16
25
10
15
4
23
5 5
Keine Loesung!
2 3
46
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ Ȭȱ ǰȱ ȱ ȱ ȱ £ǯȱ ǯǯȱ
ȱȱŗŞŘřȱȱȱǰȱȱȱȱȱȱãȱȱȱ
£ȱȱãȱûǯȱȱȱ ȱȱȱ £ȱȱ ȱ ȱ ãȬ
ȱȱǰȱȱȱûȱȱǰȱ ȱȱȱûȱ
¡ǯȱȱȱȱȱ ǰȱȱȱ §ȱȱ£ ǯȱȱ
ǰȱȱȱȱ£ȱȱȱãȱ ǯȱȱ§Ȭ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ãȱ
ûȱȱȱȱDZȱȱ ȱȱȱȱȱ§ȱȱǰȱȱ
ȱȱǰȱ£ûȱȱ£ȱ ǰȱ ȱȱȱȱȱȱ Ȭ
ȱȱȱȱȱȱȱ ȱãǯȱ
ȱȱ
ȱȱ ȱȱȱ¡ȱǽǾǽǾȱǯȱȱȱȱȬ
ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ¢ȱ ¡ǽǾȱ ȱ ¢ǽǾȱ
ȱǻȱǼǯȱȱ ȱȱȱȱǻ¡ǰȱ¢ǼȱǰȱȱȱȱȬ
ȱȱãȱ¡Ƹ¡ǽǾǰȱ¢Ƹ¢ǽǾȱȱƽŖǰǯǯǯǰŝǯȱȱȱ ǻǼȱȱ
ȱ £ȱ ȱ ȱ £ûǰȱ ȱ ȱ ȱ ȱ ȱ ǻ¡ǰȱ ¢Ǽȱ ȱ £ȱ
ȱ ǻȱ ȱ ȱ ȱ ȱ ûǼǯȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǻǼDZȱ ȱ ãȱ ȱ ȱ ûȱ
ȱȱ£ ǯȱȱȱȱȱȱ£ȱȱ ȱûȱ ȱ£ûȬ
ǯȱȱȱȱǰȱ ȱȱȱȱȱȱȱȬ
ǰȱȱȱȱȱǯȱȱȱȱȱǰȱȱȱȱȱȬ
ȱǻȱȱ£ȱȱ ȱûǼȱȱȱ ȱ¡ȱȱ¢ȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ
ȱǰȱȱ ȱȱȱǻǼȱǯȱȱȱȱ
£§ȱȱûȱȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P03Knight {
private static final String FileInputName = "springer.in";
private static final String FileOutputName = "springer.out";
private static final int dx[] = { -2, -2, -1, -1, 1, 1, 2, 2 };
private static final int dy[] = { -1, 1, -2, 2, -2, 2, -1, 1 };
private static boolean onTheTable(int x, int y, int m, int n) {
return (0 <= x && x < m) && (0 <= y && y < n);
}
3
Greedy
47
private static int nrAllowedSteps(int a[][],
int m, int n, int x, int y) {
int nr = 0;
int xn, yn;
for (int i = 0; i < 8; i++) {
xn = x + dx[i];
yn = y + dy[i];
if (onTheTable(xn, yn, m, n) && a[xn][yn] == 0)
nr++;
}
return nr;
}
static boolean findBestSucc(int a[][], int m, int n, int xy[]) {
int aux = Integer.MAX_VALUE;
int xn, yn, xx = 0, yy = 0;
for (int i = 0; i < 8; i++) {
xn = xy[0] + dx[i];
yn = xy[1] + dy[i];
if (onTheTable(xn, yn, m, n) && a[xn][yn] == 0) {
int steps = nrAllowedSteps(a, m, n, xn, yn);
if (steps < aux){
aux = steps;
xx = xn;
yy = yn;
}
}
}
if (aux < Integer.MAX_VALUE) {
xy[0] = xx;
xy[1] = yy;
return true;
}
return false;
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
int m = scanner.nextInt();
int n = scanner.nextInt();
int l = scanner.nextInt();
int c = scanner.nextInt();
l--;
48
Grundlegende Algorithmen mit Java
c--;
int[][] a = new int[m][n];
a[l][c] = 1;
int ctr = 1;
int xy[] = new int[2];
xy[0] = l;
xy[1] = c;
while (findBestSucc(a, m, n, xy)) {
a[xy[0]][xy[1]] = ++ctr;
}
if (ctr == m * n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
out.printf("%4d ", a[i][j]);
}
out.println();
}
} else {
out.println("Keine Loesung!");
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ȱȱȱȱȱûȱȱǯȱ
Problem 4. Minimaler Spannbaum (Kruskal-Algorithmus)
ȱ ȱ ȱ £§ȱ ãǰȱ ȱ £ȱ ȱ
ȱ£ȱDZȱ
ȱ ŗǯȱ ȱ ȱ ȱ ȱ ȱ ƽǻǰȱ Ǽǰȱ ȱ ȱ ȱ
ȱǰȱȱȱȱ ȱǻǰȱǯȱǼȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ )ǰȱ ȱ ȱ ȱ
ǻãǰȱǯȱǼȱǯȱ
ȱ Řǯȱ ȱ ȱ ȱ ȱ ƽǻǰȱ Ǽȱ ȱ ȱ
ȱ ƽǻǰȱǼȱȱȱǰȱȱ§ȱȱǻ ȱȱȱ
ǰȱȱȱȱ ȱȱ ȱ Ǽǯȱȱ
3
Greedy
49
ȱřǯȱȱ ƽǻǰȱǼȱȱ ǯȱȱȱDZȱȱŘȱ[ ǰȱȱȱ ȱȱȱȱ
ȱȱȱȱȱǰȱȱȱ ȱȱ ȱ ǯȱ
ȱ Śǯȱ ȱ ƽǻǰȱ Ǽȱ ȱ ȱ ȱ ȱ ƽǻǰȱ Ǽǯȱ ȱ ȱ ȱ
ȱ ȱ£ȱȱȱȱȱ ȱȱ DZȱȱ
ȱ
c( H ) =
¦ c(e) ǯȱ
e∈E
ȱ
ȱ śǯȱ ȱ ȱ ȱ ƽǻǰȱ Ǽȱ đȱ £§ǰȱ ȱ ûȱ ȱ
£ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ǰȱ ȱ ȱ ȱ ȱ §ǯȱ
ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £Ȭ
§ǯȱ
ȱ Ŝǯȱ ȱ ƽǻǰȱ Ǽȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ §ǰȱ ȱ
ǰȱȱ ȱȱȱǯȱ
ȱ ŝǯȱ ȱ £§ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ǰȱȱ ȱ§ȱǯȱȱ
ȱȱȱȱ§ȱ
ȱ
ȱ Şǯȱ ȱ ȱ ƽǻǰȱ Ǽȱ ȱ ȱ ƽǻǰȱ Ǽǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱǰȱđȱǯȱ
ȱ şǯȱ ȱ ǰȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ
ȱ ȱǰȱȱȱȱǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
50
Grundlegende Algorithmen mit Java
ȱ
ȱ
ȱ
ś
ȱ
ȱ
2
6 4
ȱ
ȱ
ȱ
5
9
Ŝ
7
ř
9 10
4
3
ŗ
8
2
9
Ş
3
ŗŖ
1
9
ŝ
Ř
4
Ś
8
18
9
9
ş
ȱȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱȱ ǯȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
DZȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǻŗȱ ≤ȱ ȱ ≤ȱ ŘŖŖǼȱ ȱ ȱ ȱ
§ȱȱȱȱȱ¡ǰȱȱȱ ȱȱ ȱǯȱ ȱȱ
ǽǾǽǾǁŖǰȱȱȱȱ ȱȱ ȱǻǰȱǼǯȱ ȱǽǾǽǾƽŖǰȱȱȱȱ ȱǻǰȱ
ǼǯȱȱȱǽǾǽǾȱȱȱȱǯȱȱȱȱȱ §ǰȱȱ
ȱ ȱ ȱ ȱ ¡ǯȱ DZȱ ȱ ȱ ȱ ȱ ȱ
ǯȱûȱȱ ȱȱȱȱȱȱȱȱ ȱȱȱ
ȱ ȱ ȱ ǯȱ đȱ ȱ ȱ ȱ ȱ ǯȱ
DZȱ
ȱ
kruskal.in
kruskal.out
(2, 3) -> 1.0
10
(6, 7) -> 2.0
0 4 3 10 0 0 0 0 18 0
(6, 8) -> 2.0
4 0 1 0 5 0 0 0 0 0
(1, 3) -> 3.0
3 1 0 9 5 0 0 0 0 0
(8, 10) -> 3.0
10 0 9 0 7 8 0 9 8 0
(2, 5) -> 5.0
0 4 5 7 0 9 9 0 0 0
(4, 5) -> 7.0
0 0 0 8 9 0 2 2 0 0
(4, 6) -> 8.0
0 0 0 0 9 2 0 4 0 6
(4, 9) -> 8.0
0 0 0 9 0 2 4 0 9 3
-------------------18 0 0 8 0 0 0 9 0 9
Gewicht: 39.0
0 0 0 0 0 0 6 3 9 0
3
Greedy
51
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ £ȱ ȱ ȱ ȱ §ȱ ȱ
ȱȱ ȱȱǯȱȱȱȱȱȱȱȱǰȱȱȱ
ȱ ȱ ȱ ȱ ȱ ǻǯȱ ŘşǯŖŗǯŗşŘŞǰȱ ȱ Ǽȱ
ȱ ȱŗşśŜȱȱȱȱȱȱȱ¢ȱȱ ǯȱ
ȱ ȱ ȱ ǻŗşśŜǼǯȱ ȱ ȱ ȱ ȱ ƽǻǰȱ Ǽȱ ȱ ȱ ȱ ȱ ȱ
ȱ DZȱ ȱ Řȱ [ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ƽǻǰȱ xǼǰȱ
ȱȱ ȱǯȱ ȱȱȱȱȱȱȱȱȱȬŗȱ ȱȬ
ǯȱȱûȱ ȱȱ ȱȱȱȱ ȱ ȱ£ǯȱȱȬ
ȱ ȱȱȱȱȬŗȱ ǯȱ£ȱ §ȱ ȱȱȱ
ȱ ȱȱȱ ȱȱȱǰȱȱȱ¢ȱȱȱȱȬ
§ȱ ȱ£ǯȱȱđǰȱ ȱȱȱûȱȱ ȱȱȬ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ
ȱ ȱ ȱ £ǯȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ŗǯȱ
ȱȱǰȱ ȱȱȬŗȱ ȱ §ȱǯȱȱ ȱȱȬ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱǯȱ
ȱ
ȏ ǻ ȱ Ǽȱ
ȱ
ȱȱȱǻŗǰȱŘǰȱdzǰȱǼȱ
ȱ
ȱȱȱȱǻƜŗǰȱDzȱȱŗǼȱ¡ȱȱ
ȱ
ȱȱȱȱȱȱ ǽǾȱƜȱȱȱȱȱȱȱȱȱ ȱ
ȱ
ȱȱȱ
ȱȱȱȱȱȱȦȦȱȱ ȱ£ȱ
ȱ
ȱȱȱȏȱ
ȱ
ȱȱȱ ȱƜȱŖȱ
ȱ
ȱȱȱȱƜȱŖȱ
ȱ
ȱȱȱȱǻǀȬŗǼȱȱ
ȱ
ȱȱȱȱȱȱȱȱǻǰȱǼȱƜȱ¡ǻǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱǻ ǽǾȱƽȱ ǽǾǼȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻǰȱǼȱƜȱ¡ǻǼȱ
ȱ
ȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱȱȱȱ ǯǻǻǰȱǼǼȱ
ȱ
ȱȱȱȱȱȱȱȱ ȱƜȱ ƸǻǰȱǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱƜȱƸŗȱ
ȱ
ȱȱȱȱȱȱȱȱ¡ȱƜȱ¡ǻ ǽǾǰȱ ǽǾǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱƜȱǻ ǽǾǰȱ ǽǾǼȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱǻƜŗǰȱDzȱȱŗǼȱ¡ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȦȦȱ£ ȱ ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱ ǻȱ ǽǾƽ¡Ǽȱȱ ǽǾƜȱȱȏ ȱ
ȱ
ȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȏȱ
ȱ
ȱȱȱȱ ǰȱ ȱ
ȏ ȏ ǻ ȱ Ǽȱ
52
Grundlegende Algorithmen mit Java
ȱȱ ȱȱȱȱ £ȱǰȱȱ ȱȱȬ
ǰȱȱȱȱ ȱȱȱȱ ȱȱǯȱȱ ȱ
ȱ ȱȱȱǯǰȱȱȱȱȱȱûȱȬ
ȱǯȱȱ ȱȱȱûȱǰȱȱ ȱȱ ȱ
ȱ ȱȱãǰȱ ȱ ȱȱûȱȱȱ£ǯȱȱ
ȱ
TreeMap<Double, List<Integer>> E =
new TreeMap<Double, List<Integer>>();
ȱȱȱ£ȱȱ ȱȱ ȱǰȱ§ȱȘƸȱȱ ȱǻǰȱǼȱǻȱ
ȱȱȱȱȱȱ ȱȱ ȱȱ£ȱDZȱȱȱѥȱȱǰȱѥȱ
ȱǼǯȱȱȱ ¡ȱ¢ȱ£ȱ ȱǰȱȱ ȱ
ȱȱȱûȱȱ DZȱ
ȱ
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
double aux = scanner.nextDouble();
if (i < j && aux != 0D) {
putInMultimap(E, aux, i * n + j); ȦȦȱȱǻ¡ǰȱȘƸǼȱûȱ
}
}
}
ȱȱȱȱǻûǰȱǼȱ££ûǰȱȱ ȱȱȬ
ȱ ǻǼDZȱȱȱûȱȱȱûȱȱȱȱǻvalues
== nullǼǰȱȱ ȱȱȱǻ¢ǰȱǼǰȱ ȱȱȱȱȱǰȱȱ
ûȱȱȱȱȱȱ£ǯȱȱȱûȱȱȱûȱȬ
ȱȱǰȱȱ ȱȱȱȱȱǯȱ
ȱ
private static void
putInMultimap(TreeMap<Double, List<Integer>> mmap,
Double key, Integer value) {
List<Integer> values = mmap.get(key);
if (values == null) {
values = new ArrayList<Integer>();
mmap.put(key, values);
}
values.add(value);
}
ȱȱȱ£ȱǰȱ ȱ ȱȱ ȱ ȱȱ
ȱȱ¢ǻǼǰȱǻǼǰȱ¡ǻǼȱȱǻǼǯȱȱȱȱȱ ȱ
ǯǯ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ǯǯ ȱ ǰȱ ȱ ȱ ȱ tȬ
ǯȱ
3
Greedy
53
Programm
import java.io.*;
import java.util.*;
public class P04SpanningTree {
private static final String FileInputName = "kruskal.in";
private static final String FileOutputName = "kruskal.out";
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(
new File(FileInputName)).useLocale(Locale.ENGLISH);
out = new PrintStream(new File(FileOutputName));
int n = scanner.nextInt();
TreeMap<Double, List<Integer>> E =
new TreeMap<Double, List<Integer>>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
double aux = scanner.nextDouble();
if (i < j && aux != 0D) {
putInMultimap(E, aux, i * n + j);
}
}
}
int C[] = new int[n];
for (int i = 0; i < n; i++)
C[i] = i;
TreeMap<Double, List<Integer>> H =
new TreeMap<Double, List<Integer>>();
int szH = 0;
while (szH < n - 1) {
TreeMultimapIterator it =
new TreeMultimapIterator(E);
it.next();
int uu = it.value().intValue() / n;
int vv = it.value().intValue() % n;
while (C[uu] == C[vv]) {
it.next();
uu = it.value().intValue() / n;
vv = it.value().intValue() % n;
}
putInMultimap(H, it.key(), it.value());
szH++;
it.remove();
int mi = Math.min(C[uu], C[vv]);
54
Grundlegende Algorithmen mit Java
int ma = Math.max(C[uu], C[vv]);
for (short i = 0; i < n; i++)
if (C[i] == ma)
C[i] = mi;
}
double cost = 0;
Set<Map.Entry<Double, List<Integer>>>
hEntries = H.entrySet();
for (Map.Entry<Double, List<Integer>> entry : hEntries) {
List<Integer> values = entry.getValue();
double key = entry.getKey();
for (int value : values) {
ǮȬȃȱ
out.printf("(%d, %d) -> ",
value / n + 1, value % n + 1);
out.println(key);
cost += key;
}
}
out.println("--------------------");
out.println("Gewicht: " + cost);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
private static void
putInMultimap(TreeMap<Double, List<Integer>> mmap,
Double key, Integer value) {
List<Integer> values = mmap.get(key);
if (values == null) {
values = new ArrayList<Integer>();
mmap.put(key, values);
}
values.add(value);
}
private static class TreeMultimapIterator {
private Iterator<Map.Entry<Double, List<Integer>>> mmapIt;
private ListIterator<Integer> currValuesIt;
private Integer currValue;
3
Greedy
55
Map.Entry<Double, List<Integer>> currEntry;
TreeMultimapIterator(TreeMap<Double, List<Integer>> mmap) {
this.mmapIt = mmap.entrySet().iterator();
}
boolean next() {
if (this.currValuesIt != null &&
this.currValuesIt.hasNext()) {
this.currValue = this.currValuesIt.next();
return true;
} else if (mmapIt.hasNext()) {
this.currEntry = this.mmapIt.next();
this.currValuesIt =
this.currEntry.getValue().listIterator();
this.currValue = this.currValuesIt.next();
return true;
} else {
return false;
}
}
Double key() {
return this.currEntry.getKey();
}
Integer value() {
return this.currValue;
}
void remove() {
this.currValuesIt.remove();
if (this.currEntry.getValue().isEmpty()) {
this.currValuesIt = null;
this.mmapIt.remove();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱȱȱȱ ȱȱȱȱȱ
ȱǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱ ȱȱȱǰȱȱȱȱȱǯȱ
56
Grundlegende Algorithmen mit Java
Problem 5. Huffman-Kodierung
ȱ ȱ ȱ ŘŜŘȱ ȱ ȱ ¡ȱ ȱ
ȱȱǯȱȱ¡ȱȱȱȱ
ȱȱǰȱǰȱǰȱ¡ǰȱ¢ǰȱȱ£ǰȱ ȱȱŗŖŖȱ
ǰȱȱŗŝȱǰȱȱ£ ǰȱ¡ȱśŞȱǰȱ¢ȱŞŖȱȱȱ£ȱûȱ
ǯȱȱ
ȱ
tȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ Ŗȱ
ȱ ŗȱ £ȱ §ǯȱ ȱ ȱ ûȱ ȱ ȱ ¡ȱ ȱ ȱ ȱ
§ǰȱ ȱ ȱ ȱ ȱ ȱ £ȱ £ ǯȱ ȱ ȱ ȱ
ȱȱȱ§ȱ §ȱ ûǰȱ §ȱȱȱȱûȱȱȱȱ
ȱãǯȱDZȱƽŖŖŖǰȱƽŖŖŗǰȱƽŖŗŖǰȱ¡ƽŖŗŗǰȱ¢ƽŗŖŖǰȱ£ƽŗŖŗǯȱ ȱȱ
ȱ¡ȱŘŜŘȱȉȱřȱƽȱŝŞŜȱȱ£ǯȱ
ȱ
ȱȱȱȱȱȱȱ§ǰȱȱȱȱȱ£ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ £ȱ ȱ §ȱ
ȱȱ ǯȱȱûȱȱ¡DZȱƽŖǰȱƽŗŗŖŗǰȱƽŗŗŖŖŖǰȱ¡ƽŗŗŗǰȱ¢ƽŗŖǰȱ
£ƽŗŗŖŖŗǯȱȱ £ȱȱȱȱûDZȱŗŖŖȉŗȱƸȱȱŗŝȉŚȱƸȱŘȉśȱȱƸȱȱśŞȉřȱƸȱŞŖȉŘȱƸȱśȉśȱƽȱ
śřŝǯȱȱȱŜŞǰřȱ£ȱȱŝŞŜǰȱȱȱȱ ȱûȱȱȱȱ
ȱ§ȱřŗǰŝȱ£ȱ£ȱǯȱ
ȱ
ȱȱȱȱȱ§ȱûȱȱ¡ȱȱŘŜŘȱȱ
ȱȱǰȱǰȱǰȱ¡ǰȱ¢ǰȱ£ȱȱȱ §ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
¡ȱ
¢ȱ
£ȱ
ȱȱ
§ȱ
ŗŖŖȱ
ŗŝȱ
Řȱ śŞȱ ŞŖȱ
śȱ
Ȭȱ
ŝŞŜȱ
ȱ§ȱ
ŖŖŖȱ ŖŖŗȱ
ŖŗŖȱ Ŗŗŗȱ ŗŖŖȱ
ŗŖŗȱ
śřŝȱ
ȱ§ȱ
Ŗȱ ŗŗŖŗȱ ŗŗŖŖŖȱ ŗŗŗȱ ŗŖȱ ŗŗŖŖŗȱ
ȱ
ȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ ûǰȱ ȱ ȱ §ȱ
ȱ ȱ ȱ §¡ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ §¡ǰȱ ȱ ȱ ȱ ȱ ȱ ǻ Ǽȱ ȱ
ȱ ȱ ǯȱ ȱ § ȱ ŗŖŗŗŖŖŖŗŗŖŖŗŖŗŗŗȱ ȱ ȱ
ȱ£ȱ¢£¡ȱǯȱ
ȱ
ȱȱ ȱǻŗşŘśȬŗşşşǼȱȱŗşśŘȱǻȱ ȱȱȱ ǯǯǯǰȱǯȱŗŖşŞȬŗŗŖŘǼȱ
ȱ§¡ȱǯȱ ȱ ȱȱ§ǰȱȱ§ȱȱ
ȱȱ¢ǯȱȱ ȱûȱȱȱȱǰȱȱ
ȱȱȱȱȱ£ȱȱ£ȱȱ§ȱȱȱŖȱǰȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ŗǰȱ ȱ ȱ ȱ ȱ ǯȱ Ȭ
3
Greedy
57
§ȱȱ§ȱǻȱ ȱȱȱȱ£ ȱ§Ǽȱȱ ȱȱ
§ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ûȱ ȱ ȱ
ǰȱȱȱȱȱ§ǯȱ
ȱ
ȱ ȱȱȱȱ£ǰȱȱȱȱȩȩȱ§ȱǻȱûȱȱ
Ǽȱ ȱ ȩȩȬŗȱ ǯȱ ȱ ǻǼȱ ȱ §ȱ ȱ ȱ ȱ ȱ
ȱ ǻǼȱ ȱ ȱ ȱ ȱ ǻȱ £ȱ ȱ ȱ ȱ Ǽǰȱ ȱ ȱ
ȱûȱȱ¡ȱ
¦ f (c) ⋅ h(c) ȱȱȱȱȱ£ȱȱȱȱ ȱ
c∈C
ȱǯȱȱ
ȱ
ȱȱ ȱȱȱȱȱ ¢ȱDZȱȱ§ȱ
ȱ ȱ ȱ ȱ ȩȩȱ ȱ ȱ ȱ ûȱ ȱ ȩȩȬŗȱ
£ȱ ȱ ȱ đȱ ȱ §ȱ £ȱ ǯȱ ȱ
ȱȱȱȱ£ ȱ§ȱ ŗȱ ȱŘȱȱ ȱ ȱǰȱȱ£ȱ
ȱȱȱ£ȱ ǰȱȱŗȱȱŘȱȱ§ȱȱȱȬ
ȱ ȱȱȱȱ ȱȱŗȱȱŘȱǯȱȱ
ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ ȱ ǰȱ ȱ ȱ Ȭ
ȱ ȱ ¡ȱ ȱ ȱ §ȱ ȱ ȱ ǯȱ DZȱ ȱ ȱ ȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻǰȱ §Ǽǯȱ ȱ ȱ ȱ
ȱȱȱǰȱȱ §ȱȱûȱȱ£ ȱ
ŗȱ ȱ ŗŖŖŖǯȱ DZȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯǰȱ ȱȱDZȱ
ȱ
huffman.in
huffman.out
p 100
p
0
q 17
y
10
r 2
r
11000
x 58
z
11001
y 80
q
1101
z 5
x
111
Problemanalyse und Entwurf der Lösung
ȱ £ǰȱ ȱ ȱ Ȭȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱDZȱ
ȱ
ȱ
ȱ
r:2
z:5
q:17
x:58
y:80
p:100
58
Grundlegende Algorithmen mit Java
ȱȱȱȱ§ȱȱȱ ȱȱȱ£DZȱ
ȱ
ȱ
ȱ
ȱ
ȱ
7
r:2
q:17
x:58
y:80
p:100
z:5
£ȱ£ȱ ȱȱ§ȱȱȱ ȱŝȱȱŗŝDZȱ
ȱ
ȱ
24
y:80
p:100
x:58
ȱ
ȱ
7
q:17
ȱ
ȱ
ȱ
r:2
z:5
ȱ
ȱȱ§ȱȱȱ ȱŘŚȱȱśŞDZȱ
ȱ
82
y:80
ȱ
p:100
ȱ
ȱ
24
x:58
ȱ
ȱ
7
ȱ
q:17
ȱ
ȱ
r:2
z:5
ȱ
ȱ
ȱ§ȱȱȱ ȱŗŖŖȱȱŗŜŘDZȱ
ȱ
162
p:100
ȱ
ȱ
82
y:80
ȱ
ȱ
ȱ
24
x:58
ȱ
ȱ
7
ȱ
q:17
ȱ
ȱ
r:2
z:5
3
Greedy
59
ȱȱȱ£ȱ£ȱȱȱȱǰȱȱȱ ȱȱȱ Ȭ
ȱȱŖȱȱŗȱǯȱ
ȱ
262
ȱ
1
0
ȱ
ȱ
162
p:100
0
1
ȱ
ȱ
82
y:80
ȱ
0
1
ȱ
ȱ
24
x:58
0
1
ȱ
ȱ
7
q:17
ȱ
0
1
ȱ
ȱ
r:2
z:5
ȱ
ȱȱ§ȱ§ȱãȱ ȱȱ Ȭ ȱȱȬ
ȱǰȱ ȱ ȱȱȱȱȱ£ȱȱ£ȱ ȱȱ
ǯȱ
ȱȱȱDZȱ
ȱ
ȱ
ȏ ǻǼȱ
ȱ
ȱȱȱȱѥû§ǻǼȱ
ȱ
ȱȱȱȱǻȱȱȱȱȱǼȱȱ
ȱ
ȱȱȱȱȱȱȱŗǰȱŘȱѥ§ǻǼǰȱȱ
ȱ
ȱȱȱȱȱȱȱǯȱǻŗǰȱŘǼȱ
ȱ
ȱȱȱȱȱȱȱȱѥ£ǻŗǰȱŘǼȱ
ȱ
ȱȱȱȱȱȱȱǯǻǼȱ
ȱ
ȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱ ǻǼȱ
ȱ
ȏȱ
ȏ ǻǼȱ
ȱ
ȱ
ȱ ¡§ȱȱȱȱǻȱȱǼȱȱȱȱȱȱ
ȱ§ǯȱȱ Ȭȱûȱ£ȱȱȱ ǰȱȱ
ȱȱȱȱȱȱ ǯȱ ȱûȱȱȱ£ǯȱ
ǯȱȱǽŖŚǾȱȱǽ şŝǾǯȱ
ȱ
60
Grundlegende Algorithmen mit Java
ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ §ȱ ȱ ûȱ
ȱ §ǰȱ ȱ £ ȱ ȱ ǰȱ £ȱ £ȱ ȱ ȱ §ǰȱ
ǰȱ ȱȱȱȱȱȱǰȱȱȱǯȱȱ ȱȱ
§ȱȱȱȱȱȱȱ¢ȱȱǰȱ ȱȱûȱȱ
ȱǯȱȱȱ ȱ£ ȱ§ȱȱȱȱãǰȱȱ
ȱȱȱȱ§ǯȱȱûȱȱȱȱȱ ȱ
ȱ ȱ ȱ ǻǼȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
§ȱȱǯȱ ȱȱȱ ȱȱȱǰȱȱ ȱȱȱȱ
§ȱȱȱ ȱ£ȱȱȱȱȱǻ ȱȱ
ǻȱǰȱȱǼǼǰȱȱȱȱȱȱȱãǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P05HuffmanCode {
private static final String FileInputName = "huffman.in";
private static final String FileOutputName = "huffman.out";
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
TreeMap<Integer, List<Node>> map =
new TreeMap<Integer, List<Node>>();
while (scanner.hasNext()) {
String s = scanner.next();
`
Integer cost = new Integer(scanner.nextInt());
List<Node> list = map.get(cost);
if (list == null) {
list = new ArrayList<Node>();
map.put(cost, list);
}
list.add(new Node(cost, s.charAt(0)));
}
if (map.isEmpty())
return;
while (map.size() > 1) {
Iterator<Map.Entry<Integer, List<Node>>>
it = map.entrySet().iterator();
Map.Entry<Integer, List<Node>> entry = it.next();
3
Greedy
61
ListIterator<Node> listIt = entry.getValue().listIterator();
Node first = listIt.next();
listIt.remove();
if (!listIt.hasNext() && !listIt.hasPrevious()) {
it.remove();
entry = it.next();
listIt = entry.getValue().listIterator();
}
Node second = listIt.next();
listIt.remove();
if (!listIt.hasNext() && !listIt.hasPrevious()) {
it.remove();
}
Node newNode = new Node(first, second);
List<Node> list = map.get(newNode.getCost());
if (list == null) {
list = new ArrayList<Node>();
map.put(newNode.getCost(), list);
}
list.add(newNode);
}
out = new PrintStream(new File(FileOutputName));
map.entrySet().iterator().next().getValue().
iterator().next().writeCosts(
out, new ArrayList<Boolean>());
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
class Node implements Comparable<Node> {
private int cost;
private char ch;
Node left, right;
Node(int cost, char ch) {
this.cost = cost;
this.ch = ch;
}
Node(Node left, Node right) {
62
Grundlegende Algorithmen mit Java
this.left = left;
this.right = right;
this.cost = left.cost + right.cost;
}
int getCost() {
return cost;
}
public int compareTo(Node o) {
return this.cost - o.cost;
}
void writeCosts(PrintStream out, List<Boolean> pathPrefix) {
if (left == null || right == null) {
// Blattknoten
out.print(this.ch);
out.print('\t');
for (Boolean b : pathPrefix) {
out.print(b.booleanValue() ? 1 : 0);
}
out.println();
} else {
pathPrefix.add(Boolean.FALSE);
left.writeCosts(out, pathPrefix);
pathPrefix.set(pathPrefix.size() - 1, Boolean.TRUE);
right.writeCosts(out, pathPrefix);
pathPrefix.remove(pathPrefix.size() - 1);
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
śǯ
ȱȱȱ Ȭ§ȱûȱȱ ȱȱãȱǰȱ
ȱȱ ǯȱ
ȱǰȱȱȱ Ȭȱ £ȱȱȱ ȱ
ûǯȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ Ȭ
£ȱ ȱ Ȭ ȱ ûȱ ȱ ȱ ȱ ȱ §ȱ
ǯȱ
£ȱȱȱȱǰȱȱȱȱ¡ȱȱǰȱȱȱ
ȱȱȱǯȱ
ȱ ǰȱ ȱ ȱ §ȱ §ȱ ȱ ȱ ȱ ȱ Ƹŗȱ
§ȱǯȱ
3
Greedy
Ŝǯ
63
ȱǰȱȱȱ£ȱȱ§ȱ§§ȱȱȱ ȱȱ
ȬȱȬȱDZȱ Cn =
1 § 2n ·
¨ ¸ ǯȱ
n + 1 ¨© n ¸¹
ȱ
ȱ
Řȱȱ ȱ
ȱ
řȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱŗŚȱ§ȱ§§ȱȱŚȱȱ ǯȱȱ
ȱ
ȱ
ȱȱ¢ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱǯȱ§ȱȱ ãȱ
ȱ
Data Ordering Problem
4
ȱ
ȱȱ ȱȱ ȱȱȬ§ȱȱǰȱȱȱȬ
ȱ ȱ ȱ ȱ ȱ ȱ ãȱ DZȱ £§ȱ ãȬ
ǰȱ ¡ȱ ȱ ¢ǯȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ §£ȱ £ȱ ãǯȱ ȱ Ȭ
ȱ ȱȱȱ§ǰȱ ȱȱȱȱȱȬ
ȱ ǯȱ ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £DZȱ Ȭ
ǰȱ ȱȱȱȱ§ȱȱȱ¡ȱȬ
ȱ ȱ ȱ Ȭǰȱ Ȭȱ ǻǮȱ Ȭ §Ȭ
ȃǼǰȱ ȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ Ȭ
ǰȱ Ȭǰȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
¢ȱǻȱȱȱ ȱŜȱ£ȱǼǰȱȱȱ Ȭ
£Ȭǯȱȱ
Problembeschreibung
ȱȱȱȱȱȱȱȱ§ ãȱȱ§ȱǻǼǯȱ
ȱȱȱǰȱȱûȱȱȱȱȱȱȱǰȱ Ȭ
ȱ ȱȱȱ ȱǯȱȱ ȱȱȱȱȱãȱûȬ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ £ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ûǯȱ ȱ ûȱ ȱ ȱ § ǰȱ ȱ ȱ ȱ ȱ
ȱ ȱûǰȱȱ ȱȱȱȱ§ȱȱȱȱ
§ȱǯȱȱȱȱȱȱȱȱǯȱȱȱ
ȱ§ ȱûȱ ǰȱȱ ȱȱ£ ȱȱȱȱ ȱ
ǮŗȱřȱŜȱŞȃȱûȱȱǰȱ ȱȱȱ£ ȱȱȱȱȱ
ȱȱǯȱȱ§ȱȱûȱ ǰȱ ȱȱȱǮŗȱřȱŜȱŞȃȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱŗǰȱřǰȱŜȱȱŞǯȱȱȱȱȱ£ ȱ§ ǯȱ ȱ
ȱȱȱȱ§ȱȱȱ ȱȱ£ ȱȱȱȬ
ȱŗȱȱśǯȱȱȱȱȱȱȱȱȱ§ȱȬ
ǯȱ
ȱ
§ ȱ
ǰȱȱûȱȱ ȱȱ ȱ
£ȱ
ŖȱŗȱŖȱŖȱŗȱŗȱŗȱŖȱ ŖȱŗȱŖȱŖȱŗȱŗȱŗȱŖȱ
Ŗȱ
ŗȱŗȱŗȱŖȱŗȱŖȱŗȱŗȱ ŗȱřȱŜȱŞȱ
Śȱ
ŖȱŗȱŗȱŖȱŖȱŖȱŗȱŗȱ ŗȱśȱ
Řȱ
ȱ
66
Gundlegende Algorithmen mit Java
ȱǰȱȱȱȱ£ ȱ£ ȱȱȱȱȬ
ȱ £ǰȱ £ȱ ȱ ȱ ǯȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱȱãȱȱ§ȱȱ£ ǯȱȱ ǯȱ ȱ
ãȱ ȱȱȱȱãȱȱ §ǰȱȱȱ £ȱȱȬ
ȱȱ ǯȱȱȱȱȱȱǰȱ£ȱǰȱȱȬ
ȱǮȱȱȃǯȱ
ȱȱȱȱŗşşŚȱȱȬȱȱǰȱȱȱȱãȱ
ȱȱtȱȱȱ ȱãǰȱȱȱ£ȱ ȱ
£ȱȱǻǽşŚǾǼǯȱȱ
ȱ
ȱ ŗǯȱ ȱ ȱ ȱ ȱ § ȱ ȱ ȱ ȱ ǰȱ
ȱ £ȱ ȱ ȱ ȱ ȱ £ȱ £ȱ ǻŖȱ →ȱ ŗǰȱ ŗȱ →ȱ ȱ ŖǼǯȱ ȱ w ȱ
£ȱ ȱ ȱ ȱ £ ǯȱ ȱ ȱ ȱ ȱ ǯȱ DZȱ ȱ ƽȱ
ŗŖŗŗŖŖŖŗǰȱ w ȱȱƽȱŖŗŖŖŗŗŗŖȱȱ 10110 = 01001 ǯȱ
ȱ
ûȱ ȱ Ȭȱ ǻ ȱ ƽȱ ȱ ȱ Ǽȱ ȱ ǰȱ ȱ ȱ ȱ
§ ãȱȱȱȱȱûǯȱȱ ȱȱûȱȱȱǰȱ
ȱ ȱȱȱ¡Ȭȱûȱȱ ǰȱȱȱ££ǯȱȱȱȮȱ
ȱ ȱ ȱ ȱ ȱ Ȯȱ ȱ Ȭ§ǯȱ ȱ ȱ ȱ
ȱ ȱȱȱ¡ȱûȱȱȱ ȱ£ǯȱǯȱȱȱȱ ȱ
ȱ ȱ ǻ Ȭ ȱ Ǽǰȱ ȱ ȱ tȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱǯȱȱ
Problemdomäne, Definitionen
ȱŘǯȱ Ȭ£ǯȱȱ ȱȱȱ ȱȱȱȱ ȱûǰȱ
ȱȱ£ȱȱãȱȱȱ
k
d ( wr , ws ) = ¦ wrj ⊕ wsj ǰȱȱȱȱ§ȱȱȱãȱȱȱȱǻŗǼǰȱ
j =1
ȱ ȱ £ȱ ȱ ȱ Ȭ£ȱ £ ȱ ȱ ȱ ǯȱ ȱ ȱ ǻŗǼȱȱ
ȱȱ ȱȱȬȱȱȱȱ§ȱȱ ȱȱȱ⊕ȱȱȱȱȱ¡Ȭ
ȱDZȱ
¡ȱ ¢ȱ ¡⊕¢ȱ
Ŗȱ Ŗȱ Ŗȱ
Ŗȱ ŗȱ ŗȱ
ŗȱ Ŗȱ ŗȱ
ŗȱ ŗȱ Ŗȱ
ȱ
DZȱǻŗŖŖŖŗŗŗŖǰȱŗŖŗŗŖŗŗŗǼȱƽȱŚǯȱ
4 Data Ordering Problem
67
£ȱŗǯȱȱȱȱȱȱ£ȱǯȱȱ Ȭ£ǰȱȱȱȱȱȱ
ãȱ ȱ §ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱûDZȱ
ȱ
ǻŗǼȱǻ¡ǰȱ¢Ǽȱ≥ȱŖȱûȱȱ¡ǰȱ¢∈ȱǰȱǻ¡ǰȱ¢ǼȱƽȱŖȱ⇔ȱ¡ȱƽȱ¢ȱ
ǻŘǼȱ¢DZȱǻ¡ǰȱ¢Ǽȱƽȱǻ¢ǰȱ¡Ǽȱûȱȱ¡ǰȱ¢∈ȱȱ
ǻřǼȱDZȱǻ¡ǰȱ¢Ǽȱ≤ȱǻ¡ǰȱ£ǼȱƸȱǻ£ǰȱ¢Ǽȱûȱȱ¡ǰȱ¢ǰȱ£ȱ∈ȱȱ
DZȱ
ŗǯȱȱǻ¡ǰ¢ǼȱƽȱŖȱDZȱȱ
k
¦ d ( x , y ) = 0 ȱȱȱȱȱBȱȱûȱȱƽŗǰȱdzǰȱȱȱȱ¡ ȱȱƽȱȱ¢ ȱȱǻ¡ ȱȱ¢ ȱȱȱǰȱȱȱȱ
j
j
j =1
ãȱ¡ȱȱ¢ȱǼǯȱ
ȱ
Řǯȱȱ¢ȱȱȱȱȱ¢ȱȱȱ⊕ǯȱ
řǯȱȱȱǰȱȱȱãȱ¡ǰȱ¢ȱȱ£ȱȱ§ȱ¡ŗǯǯǯ¡ǰȱ¢ŗǯǯǯ¢ȱȱ
£ŗǯǯǯ£ȱǯȱȱȱȱûȱãȱȱ§ȱŗȱ ȱȱ ȱȱȱǰȱȱȱȱ
ǰȱȱȱ ȱûȱȱûȱǻǰȱǼȱȱǻǰȱǼƸǻǰȱǼȱȱDZȱ
ȱȱûȱǻǰȱǼȱȱǻǰȱǼȱƸȱǻǰȱǼȱ
ȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
ŗȱ
ŗȱ
ŗȱ
ȱ
Ŗȱ
Ŗȱ
ŗȱ
ŗȱ
Ŗȱ
Ŗȱ
ŗȱ
ŗȱ
ȱ ǻǰȱǼȱ ǻǰȱǼȱƸȱǻǰȱǼȱ
Ŗ
Ŗȱ
Ŗȱ
ŗ
Ŗȱ
Řȱ
Ŗ
ŗȱ
ŗȱ
ŗ
ŗȱ
ŗȱ
Ŗ
ŗȱ
ŗȱ
ŗ
ŗȱ
ŗȱ
Ŗ
Ŗȱ
Řȱ
ŗ
Ŗȱ
Ŗȱ
ȱ
ȱȱǰȱȱȱȱûȱȱãȱȱ§ȱŗȱûȱǰȱ
ȱȱǰȱȱȱȱûȱãȱȱ§ȱ ȱǰȱ ȱ ȱȱȱȬ
ǯȱ÷ȱ
ȱ
ȱřǯȱ £ȱȱǯȱ ȱȱȱ§ ãȱ ŗǰȱ Řǰȱǯǯǯǰȱ
ǰȱ ȱ ȱ σȱ ǻȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ
68
Gundlegende Algorithmen mit Java
ȱ ǿ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȀǼȱ ȱ ȱ ȱ δȱ ǻȱ ȱ ȱ ȱ
ȱǿŗǰȱŘǰȱǯǯǯǰȱȀȱȱȱȱǿŖǰŗȀǼǰȱȱûȱȱȱǰȱ
ȱȱȱȱȱǯȱȱ £ȱȱȱȱȱDZȱ
ȱ
NT =
n −1
¦ d (wσδ , wσδ
( j)
( j)
j =1
( j +1)
( j +1) ) ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŘǼȱ
ȱŚǯȱ££¡ǯȱûȱȱ £ȱȱȬȱȱ Ȭȱǻ ȱ
ȱ ȱ £ȱ ȱ ãȱ ȱ ȱ ȱ §ȱ Ǽȱ ȱ ȱ ȱ ££¡ȱ
ƽǻǼȱȱȱȱƽȱǻ ǰȱ Ǽǯȱ
ȱ
DZȱûȱȱƽȱřȱȱȱƽȱśȱȱȱ££¡ȱûȱȱãȱ ŗȱƽȱŖŖŖŗŗǰȱ Řȱƽȱ
ŗŖŗŗŖȱȱ řȱƽȱŖŗŖŗŗȱȱDZȱ
ȱ
§0 3 1·
ȱ
¸
¨
ȱȱ
A = ¨ 3 0 4¸
¨ 1 4 0¸
ȱ
¹
©
ȱ
ǻȱǻ ŗǰȱ ŗǼȱƽȱŖǰȱǻ ŗǰȱ ŘǼȱƽȱřǰȱǻ ŗǰȱ řǼȱƽȱŗǰȱdzȱǼǯȱȱ
ȱ
£ûȱȱ££¡ȱȱȱDZȱ
ŗǯȱȱ££¡ȱȱ¢ȱ£ȱ ǯȱȱȱ¢ȱȱ
Ȭ£ȱȱȱ
ȱ
d ( wi , w j ) = d ( w j , wi ) aij = a ji ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻřǼȱ
ȱ
Řǯȱȱȱȱȱ ȱȱǯȱȱȱȱȱ Ȭ
£ȱǰȱȱ
ȱ
d ( wi , wi ) = 0 a ii = 0 ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŚǼȱ
ȱ
řǯȱȱ££¡ȱ§ȱȱǰȱ ȱȱȱãȱǯȱ
ȱ
d ( wi , w j ) = d ( wi , w j ) ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻśǼȱ
ȱ
Śǯȱȱȱȱ§ȱȱãȱǰȱȱ
ȱ
4 Data Ordering Problem
69
d ( wi , w j ) = d ( wi , w j ) = k − d ( wi , w j ) = k − aij ȱȱȱȱȱȱȱȱȱȱȱǻŜǼȱ
śǯȱȱ ȱȱãȱȱȱûǰȱ ȱȱȱǰȱ ȱȱ ȱȱ
ȱ §ȱ ȱ ãȱ ȱ ûǰȱ ȱ ȱ £ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ
ȱǯȱ
ȱŗǯȱ ȱȱȱƽȱřǰȱȱƽȱŗŘȱȱȱãȱ
ȱ
ŗȱƽȱŖŗŖŗŖŖŗŗŗŖŖŖȱȱȱȱȱȱȱȱ
ŘȱƽȱŖŖŗŖŗŖŗŖŖŗŗŖȱȱȱȱȱȱȱȱ
řȱƽȱŖŖŗŗŗŗŖŗŗŖŗŗȱȱȱȱȱȱȱȱ
ȱ
ȱȱȱ££¡ȱ
ȱ
§ 0 8 7·
ȱ A = ¨ 8 0 7¸
¨
¸
ȱ
¨ 7 7 0¸
©
¹
ȱ
ȱ ȱȱãȱ ȱȱǰȱȱȱ £ȱȱȱ
ȱ
N T = a12 + a 23 = 15
ȱ ȱȱȱ£ ȱȱǰȱȱ
ȱ
N T = ( k − a12 ) + ( k − a 23 ) = (12 − 8) + (12 − 7) = 9 ȱ
ȱ
ȱŚŖȱ£ȱǯȱ
ȱŘǯȱûȱȱƽȱŝǰȱȱƽȱŗśȱȱȱãȱ
ȱ
ŗȱƽȱŖŖŗŖŗŖŗŖŖŗŗŖŗŗŖȱȱȱȱȱȱȱȱ
ŘȱƽȱŖŖŖŖŖŖŖŖŗŗŗŗŗŗŖȱȱȱȱȱȱȱȱ
řȱƽȱŖŖŗŗŗŗŖŗŗŖŗŖŖŗŖȱȱȱȱȱȱȱȱ
ŚȱƽȱŖŖŖŖŗŖŖŗŗŗŗŖŗŗŗȱȱȱȱȱȱȱȱ
śȱƽȱŖŖŖŖŖŗŗŗŗŖŗŗŖŗŗȱȱȱȱȱȱȱȱ
ŜȱƽȱŖŖŖŗŗŖŖŗŖŖŖŗŗŖŖȱȱȱȱȱȱȱȱ
ŝȱƽȱŖŖŖŖŖŗŖŗŖŖŖŗŗŗŖȱȱȱȱȱȱȱȱ
ȱ
ȱ
ȱȱ££¡DZȱ
70
Gundlegende Algorithmen mit Java
ȱ
§0 5 7 5 9 8
ȱ
¨
¨5 0 8 4 6 7
ȱ
¨7 8 0 6 6 7
ȱ
¨
A = ¨5 4 6 0 6 7
ȱ
¨9 6 6 6 0 9
¨
ȱ
¨8 7 7 7 9 0
ȱ
¨
©8 5 7 7 5 4
ȱ
ȱ
ȱ ȱ ȱ ãȱ
ȱ
8·
¸
5¸
7¸ .
¸
7¸
5 ¸¸
4¸
¸
0¹
ȱ ȱ ǰȱ ȱ
ȱ ȱ
£ȱ ȱ
6
N T = ¦ a t ,t +1 = 38 ȱ
t =1
ȱ ȱȱãȱȱȱȱ
ǰȱ
ŗ
ǰȱ
Ř
ǰȱ
Ś
ǰȱ
ř
ǰȱ
ś
ǰȱ
ŝ
ȱǰȱȱ
Ŝ
NT = a12 + a24 + a43 + a35 + a57 + a76 = 30 ȱ
ȱȱȱ£ȱȱŘŜǯŝȱ£ǯȱ
ȱ
ȱřǯȱ ȱȱȱƽȱŞǰȱȱƽȱŗřȱȱȱãȱ
ȱ
ŗȱƽȱŗŗŗŗŖŗŖŗŗŗŖŖŗȱȱȱȱȱȱȱȱ
ŘȱƽȱŗŖŗŖŗŖŖŗŗŖŗŗŖȱȱȱȱȱȱȱȱ
řȱƽȱŖŖŖŖŖŖŗŗŗŗŗŗŖȱȱȱȱȱȱȱȱ
ŚȱƽȱŗŗŗŗŖŗŗŖŗŖŖŗŖȱȱȱȱȱȱȱȱ
śȱƽȱŖŖŖŗŗŗŗŖŗŗŖŗŗȱȱȱȱȱȱȱȱ
ŜȱƽȱŖŗŗŖŖŗŖŖŖŗŗŖŖȱȱȱȱȱȱȱȱ
ŝȱƽȱŖŖŖŗŖŗŖŖŖŗŗŗŖȱȱȱȱȱȱȱȱ
ŞȱƽȱŗŖŖŖŗŗŖŗŗŖŗŖŖǯȱ
ȱ
ȱȱ££¡DZȱ
ȱ
ȱ
§ 0 8 9 5 7 6 8 7·
¨
¸
ȱ
¨ 8 0 5 7 9 8 8 3¸
ȱ
¨ 9 5 0 8 6 7 5 6¸
¨
¸
ȱ
¨ 5 7 8 0 6 7 7 8¸ ǯ
ȱ
A=¨
¸
ȱ
¨ 7 9 6 6 0 9 5 8¸
¨ 6 8 7 7 9 0 4 7¸
ȱ
¨
¸
ȱûȱȱãȱ
8 8 5 7 5 4 0 ȱǯȱȱȱ
7
¨
¸
¨ 7 3 6 8 8 7 7 0¸
©
¹
4 Data Ordering Problem
71
7
N T = ¦ a t ,t +1 = 47 ȱ
t =1
ȱûȱ ȱȱDZȱ
ȱ
w1 → w3 → w4 → w8 → w2 → w5 → w6 → w7 ȱ
ȱ
ȱ£ȱȱȱ£ȱȱȱȱřŞǰřȱ£ǰȱȱ
ȱ
N T = (13 − a13 ) + (13 − a34 ) + (13 − a 48 ) + a82 + (13 − a 25 ) + a56 + a 67 = 29 ȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ ȱȱãȱȱ ȱȱãǯȱȱȱ
ȱ ȱ ȱ ȱ ȱ §ȱ ǰȱ ãȱ ȱ ȱ ¡ȱ ȱ
ǰȱȱȱȱãȱ£ȱǯȱȱȱȱȱȱ ǰȱûȱ ȱ
ȱ ȱ ǰȱ ȱ ãȱ ȱ ãȱ ǰȱ ȱ ȱ ¡ȱ
ȱȱȱȱȱǯȱ
ȱ
ȱśǯȱȱǻȱȱǼȱȱȱȱȱσȱȱȱȱ
ãȱ ŗǰȱ Řǰȱdzǰȱ ǰȱȱȱȱ £ȱȱȱ
n −1
ȱ
ȱ
NT = ¦ d ( wσ ( j ) , wσ ( j +1) ) ȱ
ȱ
ǻŝǼȱ
j =1
ȱ ǯȱ
ȱ
ȱŜǯȱ ȱǻȱȱȱȱ Ǽȱȱȱȱȱ
σȱȱȱ ȱδȱȱȱȱãȱ ŗǰȱ Řǰȱdzǰȱ ǰȱȱȱȱ £ȱ
ȱȱ
ȱ
NT =
n −1
¦
j =1
ȱ
d ( wσδ (( jj )) , wσδ (( jj ++11)) ) ȱ
ǻŞǼȱ
ȱ ǯȱ
DOP und DOPI sind NP-vollständig
ȱ ǽşśǾȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ§ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ǰȱ ȱ £ȱ ãȱ DZȱ ȱ
ȱ ǻȱ ȱ ȱ Ȯȱ Ǽǰȱ ȱ ȱ ȱ ¡ȱ
ȱ ǻȱ ȱ ȱ ¡ȱ ȱ Ȯȱ ȬǼȱ ȱ ¢ȱ ǻȱ
ǰȱȱǰȱȱȱǼǯȱ
72
Gundlegende Algorithmen mit Java
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱ ȱ ǵȱ ǰȱ ûȱ ȱ Ȭ§ȱ ȱ ȱ ȱ ȱ
¢ȱ ȱ ǯȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ ¢ȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ ȱ
Ȭ§ȱ ȱ ȱ ¢ȱ ȱ ȱ ǯȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ ȱ £ȱ ȱ ȱ
ȱ ¢ȱ ãȱ ȱ ȱ £ȱ ǯȱ ȱ §ȱ ȱ ȱ ȱ ȱ
ȱ ǰȱ ȱȱ£ȱ§ǯȱ
ȱ
ȱ ãȱǰȱȱȱȱȱȱȱ ȱȱȱ
ȱȱȱȱȱȱȱȱ ǰȱȱ£ȱȬ§ǯȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ǰȱ ǰȱ £ Ȭ
ǰȱȱȱǰȱȱȱǰȱǰȱȱȱȬ
ǰȱȬȱȱǰȱǰȱ ǯȱȱ
ȱ
ȱ ȱ ȱȱȱȱȱ ǯȱȱ
£ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ § ãȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȱ ȱ §ȱ ȱ
ǯȱȱ
ǯȱ ȱȱȱȱ σȱȱȱ ȱ δȱȱȱ ŗǰȱ Řǰȱdzǰȱ ȱ ȱ
ãǰȱȱȱ
NT =
n −1
¦ d (wσδ , wσδ
( j)
( j)
j =1
( j +1)
ȱȱȱȱȱȱǻşǼȱ
( j +1) ) ≤ m
ȱ δ ( wi ) = wi ȱȱ δ ( wi ) = wi ǵȱ
ȱ
ȱ ǰȱ ȱ ȱ Ȭ§ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱ§ȱ ȱǰȱ ȱȱȱãđȱȱ£ûȱȱȬ
ȱǯȱȱ ȱȱȱ ǰȱȱ ȱȬ§ȱǯȱ
Algorithmen für DOP und DOPI
ûȱ ȱãȱ ȱȱ¢ȱȱȱǰȱȱȱ ȱ ȱȱ
ȱ ȱ ȱ ȱ ȱ ãǯȱ ûȱ ȱ £ȱ ȱ ȱ
ȱ ȱ § ãȱ ȱ §ȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ
ǻȱ ȱ ãǼȱ ȱ ȱ ȱ ȱ §ȱ ȱ ǻȱ ȱ ȱ
ãǼǯȱ ȱ ȱ ȱ £ȱ ȱ ȱ DZȱ Ȭǰȱ
¡Ȭǰȱ£ ȱ ¢Ȭȱȱ£ȱȱȱȱȱ
ȱǻǯȱ ȱǼǰȱȱȱȱȱǯȱ
ȱ
ȱ
ȱ
4 Data Ordering Problem
73
ȱȱȱãȱ
ȱ
ȱ
ȱƽȱŖŗŖŗŗŖŖŗŗȱ
ŘȱƽȱŗŖŗŗŗŖŖŖŖȱ
řȱƽȱŖŖŗŖŖŖŖŖŗȱȱȱȱȱȱȱȱȱȱ
ŚȱƽȱŗŗŗŖŗŖŖŖŗȱ
śȱƽȱŗŗŗŖŗŗŗŗŗȱȱȱȱȱȱ
ŜȱƽȱŖŖŖŗŖŗŗŗŗȱ
ŝȱƽȱŗŖŖŖŗŖŖŖŗȱ
ŞȱƽȱŖŖŗŖŖŗŗŗŗȱ
ŗ
§0
¨
¨5
¨5
¨
££¡ȱŞşƽȱ ¨ 4
¨
¨5
¨4
¨
¨4
¨6
©
5 5 4 5 4 4 6·
¸
0 4 3 6 7 3 7¸
4 0 3 6 5 3 3¸
¸
3 3 0 3 8 2 6¸
¸
6 6 3 0 5 5 3¸
7 5 8 5 0 6 2¸
¸
3 3 2 5 6 0 6¸
7 3 6 3 2 6 0 ¸¹
ȱ
ȱ£ȱȱ£ȱȱ Şşȱǻ ȱƽŞȱȱƽşȱǼȱȱ ȱȱ
ȱ £ûǰȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ
ȱ £ȱ ǯȱ đȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ £ȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ ǰȱ ȱ ȱ ãȱ ȱ
ȱȱȱȱȱ ȱûȱ ǰȱȱřŘǯȱ
Zufällige-Lösung-Algorithmen (RAN)
ȱ§ȬãȬȱûȱȱȱȱ£§ȱȱȱ
ȱȱ£ȱȱȱȱ ȱǯȱûȱ ȱȱȱ
£§£ȱȱ£§ȱǰȱȱȱȱ ǯȱ
ȱ
ȱ
ȱ
ȏȱȏǻǰȱǰȱ ŗǯǯ Ǽȱ
ȱ
ȱ←ȱȱȱ
ȱǰȱǻǼȱ
ȏȱ ȏȱȏǻǰȱǰȱ
ȏȏ ǻǰȱǰȱ
ǯǯ
ŗ
ǯǯ
ǯǯ
ŗ
Ǽȱ
Ǽȱ
ȱ←ȱȱȱ
ȱ←ȱȱȱ
ȱǰȱǰȱǻǰȱǼȱ
ȏȱ ȏȏ ǻǰȱǰȱ
ŗ
Ǽ
74
Gundlegende Algorithmen mit Java
£ûȱ Şşȱȱȱȱȱ£ȱȱûȱȱȱǻŝǰȱŞǰȱŚǰȱŘǰȱřǰȱśǰȱ
Ŝǰȱ ŗǼȱ ȱ ȱ řŚǯȱ ȱ ȱ ȱ ûȱ ȱ ȱ ǻŝǰȱŗǰȱ řǰȱ Şǰȱśǰȱ ŘǰȱŚǰȱ ŜǼȱ
ȱȱ ȱǻŖǰȱŗǰȱŖǰȱŗǰȱŗǰȱŗǰȱŖǰȱŖǼȱ ȱȱřŞȱǯȱȱ ¡§ȱȬ
ȱȱȱǻǼǯȱ
Exakt-Algorithmen (EX)
ȱ¡Ȭȱûȱȱȱȱȱȱȱȱǰȱ
ȱ £ȱ ȱ ȱ ûǯȱ ȱ ûȱ ȱ ȱ ȱ ȱ
ǻǰȱ Ǽȱ ȱ ȱ ȱ ǰȱ ȱ £ȱ ȱ ȱ
ûǯȱ
ȏȱ ȏ ǻǰȱǰȱ
ǯǯ
ŗ
Ǽȱ
ȱ←ȱȱǻǼȱ
ȱ←ȱȱǻǼȱ
ȱǻȱǻǼȱǼȱ¡ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱǻȱǻǼȱǼȱ¡ȱ
ȱȱȱȱȱȱȱ ǻǻǰȱǼǀǻǰȱǼǼȱȱ
ȱȱȱȱȱȱȱȱȱȱȱ←ȱȱ
ȱȱȱȱȱȱȱȱȱȱȱ←ȱȱ
ȏ ȱȱȱȏȱȱȱȱȏȱ
ȱǰȱǰȱǻǰȱǼȱ
ȏȱ ȏȱ ȏ ǻǰȱǰȱ
ǯǯ
ŗ
Ǽȱ
£ûȱ Şşȱȱ ȱȱȱûȱȱȱǻŗǰȱŜǰȱŞǰȱřǰȱŘǰȱŝǰȱŚǰȱśǼȱȱ
ȱ ȱ Řŗǯȱ ȱ ȱ Ȭ ȱ ȱ ȱ ȱ ŗŜǰȱ ȱ ȱ
ȱûȱȱȱǻŗǰȱŞǰȱŘǰȱŜǰȱŚǰȱŝǰȱřǰȱśǼȱȱȱ ȱǻŖǰȱŗǰȱŖǰȱŗǰȱŖǰȱŖǰȱŖǰȱŗǼȱ
ǯȱ ȱ ¡§ȱ ȱ ȏȬȱ ȱ ǻǷǼǰȱ ȱ ȱ ȏ Ȭ
ȱȱǻǷȉŘǼǯȱȱ
Greedy_Min-Algorithmen (GM)
ȱȱ ¢ȏȬ£ȱãȱ ȱ ȱȱȱȱ ǯȱ
ȱDZȱ
• ȱȱ ȱûȱȱãȱãȱȱȱȱȱ
ǰȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ ãȱ ûȱ
ȱ ǯȱ
4 Data Ordering Problem
•
•
75
ȱȱȱȱ£ǯȱ
§ȱ ȱ £ǰȱ ȱ ȱ ȱ ȱ ǮȄȱ ȱ
ȱȱȱȱȱȱȱȱ£ȱ£ûȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ûȱ ûȱ ȱ ȱ §ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
£ȱȱǯȱȱ ȱȱȱȱȱȱ ǯȱ
ȱ
ȱ ¡§ȱȱȱȱ¢ȱǻŘǼǯȱûȱ Şşȱȱȱȱ
ȱ ȱ ȱ ǻśǰȱ ŗǰȱ Ŝǰȱ Şǰȱ řǰȱ Śǰȱ ŝǰȱ ŘǼȱ ȱ ȱ ŘŘȱ £ǯȱ ȱ ȱ
ȱȱȱȱȱǻśǰȱřǰȱŝǰȱŚǰȱŜǰȱŘǰȱŞǰŗǼȱȱȱ ȱȱǻŗǰȱŖǰȱŖǰȱŖǰȱŗǰȱ
ŖǰȱŗǰȱŖǼȱ ȱȱŗŜǯȱ
Greedy_Min Simplified-Algorithmen (GMS)
ȱ ȱ ȱ ¢ȏȬ£ȱ ǻ Ǽȱ ȱ ǯȱ ȱ £ȱ ûȱ
ȱ ãȱ ȱ ȱ ȱ ȱ £ûȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ đȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱȱ ¡§ȱȱȱȱȱ¢ȱǻŘǼǯȱ
ȱ
£ûȱ ŞşȱȱȱȱȱȱȱǻŚǰȱŝǰȱŘǰȱřǰȱŞǰȱŜǰȱŗǰȱśǼȱȱ Ȭ
ȱȱŘřȱȱȱ ȱȱȱǻŚǰȱŜǰȱŞǰȱŗǰȱŘǰȱŝǰȱřǰȱśǼǰȱȱ ȱǻŖǰȱŗǰȱ
ŗǰȱŖǰȱŗǰȱŗǰȱŗǰȱŖǼȱȱȱ ȱŗşǯȱ
Algorithmen mit unterer Schranke (LB)
ȱ ȱ ȱ ȱ ȱ ãȱ ûȱ ȱ ȱ ȱ ȱ
ȱ ǯȱ ûȱ ȱ ȱ ȱ ȱ §ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ£ȱ
ȱ ȱ ȱ ǯȱ ȱ Ȭ£ȱ £ ȱ ãȱ §ȱ ȱ ǰȱ
ȱ ȱ ȱ ãȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ
ûȱ ȱ ǻȱ ǰȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ǼDZȱ d ( wi , w j ) = d ( wi , w j ) ȱȱ d ( wi , w j ) = d ( wi , w j ) ǯȱ
ûȱ ȱ£ȱ ȱȱǰȱȱ ȱ£ ȱ ȱȱ£ ȱ ȱ
ǰȱȱûȱȱ ǯȱ ȱȱ ȱûȱ ȱȱȱ
ȱȱȱǰȱȱȱ ȱǰȱȱȱȱ
ȱȱȱȱȬ§ǯȱȱ
ȱ
ȱȱȱȱ ȱ£ ǯȱȱȱȱȱȱ§ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱđǯȱȱȱãȱȱȱǻȱȱ¡ȬȱǼȱȱ
ȱ ȱ ȱ đȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
76
Gundlegende Algorithmen mit Java
ȱ ȱ ǻǯȱ ȱ Ǽȱ ãȱ ȱ ȱ đȱ £ȱ ȱ
§£ǰȱ ȱ ȱ ȱ ¢Ȭȱ ǰȱ ȱ ȱ ¡Ȭȱ
ãȱ ȱȱȱȱ£ȱȱȱ£ǯȱ
ȱ ȱ £ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ ǰȱ
ȱȱȱǻ ȱȱ Ǽȱȱȱȱ ȱǻ ȱȱ Ǽǯȱ
ȱ £ȱ ȱ Ȭȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Śȱ ȱ ȱ
¢Ȭ ȱȱǯȱ
ȱ
£ûȱ Şşȱȱ ȱȱȱȱDZȱǻŚǰȱŝǼȱȬǁȱŘȱȩȱǻŜǰȱŞǼȱȬǁȱŘȱȩȱǻŘǰȱŚǼȱȬǁȱ
řȱȩȱǻřǰȱŚǼȱȬǁȱřȱȩȱǻřǰȱŞǼȱȬǁȱřȱȩȱǻŚǰȱśǼȱȬǁȱřȱȩȱǻŗǰȱŚǼȱȬǁȱŚǯȱ
ȱ
w1
ȱ
ȱ
4
ȱ
w2
ȱ
3
ȱ
3
w4
w8 2
w6
w3 3
ȱ
3
ȱ
2
ȱ
w5
ȱ
ȱ
ȱ
w7
ȱ
ȱȱûȱǰȱ Şşȱ
ȱ
ȱ ȱȱȱȱŘŖǯȱȱ
ȱ
ȱ ȱ£ȱ ȱȱȱǻŚǰȱŜǼȱȬǁȱŗȱȩȱǻŘǰȱŜǼȱȬǁȱŘȱȩȱǻŘǰȱŞǼȱȬǁȱŘȱȩȱǻŚǰȱŝǼȱȬǁȱŘȱȩȱǻŗǰȱŞǼȱȬ
ǁȱřȱȩȱǻŘǰȱśǼȱȬǁȱřȱȩȱǻřǰȱŚǼȱȬǁȱřȱȱȱ ȱŗŜǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
w3
w4
3
1
2
w6
2
3
w2
w5
2
w8
3
w1
w7
ȱȱûȱ ǰȱ Şşȱǻȱȱûȱãȱȱȱȱ
ȱ£ǰȱȱȱȱȱ ǯǼȱ
ȱ
ȱ ¡§ȱȱȱȱ¢ȱǻŘǼǯȱ
4 Data Ordering Problem
77
Implementierungsdetails
ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ
£ȱ ȱ ȱ ǯȱ ȱ ûȱ ȱ £ȱ ȱ ǰȱ ȱ ȱ ãȱ
ȱ ȱ ǰȱ ȱ ȱ £ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱǯȱȱȱȱǰȱȱȱȱȱ§ȱȱȬ
ȱȱȱȱ §ȱȱ£ȱ£ǯȱȱûȱȱȱ
ȱȱȱȱ ȱȱȱȱǯȱ
ȱ ȱȱǯǯȱȱȱȱȱǽǾǯȱ
ȱȱȱ ȱŖŗȏ ȱȱȱDZȱ
Ȭ DZȱ£ȱȱȱ§ ãDzȱ
Ȭ DZȱ§ȱȱãDzȱ
Ȭ
ǽǾDZȱȱ¢ȱȱȱȱ¢ȱǰȱȱȱãȱDzȱ
Ȭ ǽǾǽǾDZȱ£ ȱ¢ȱûȱȱ££¡Dzȱ
Ȭ ǽǾDZȱ¢ǰȱȱȱȱûȱ ǽǾȱDzȱ
Ȭ DZȱȱ ȱȱ¢ȱȱûȱȱãȱ ǽǾǯȱ
ȱ
ȱ ȱ Ŗŗȏ ǻȱ ǰȱ ȱ Ǽȱ ȱ ȱ £§ȱ § ãȱ ȱ ǽǾǰȱ
ȱ ȱ ȱ ȱ ȱ ££¡ȱ ȱ ȱ ȱ ȱ ǻǼȱ ȱ
ȱȱȱȱǽǾȱȱȱȱǯȱ
ȱ
ȱȱȱDZȱ
Ȭ ǻǼDZȱȱ£§ȱ §ȱȱȱȱȱ
ǽǾȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯǻǼȱ ȱ ȱ ȱ
ǯDzȱ
Ȭ ǻǼDZȱȱȱ ȱûȱȱȱȱǽǾȱȱȱ
££¡ȱǽǾǽǾǰȱȱȱȱ£ȱȱȱDzȱ
Ȭ ǻǼDZȱ ȱ ȱ ȱ ǽǾȱ ȱ ȱ ȱ Ȭ
ȱ£ûDzȱ
Ȭ ǻǼDZȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǽǾȱ ȱ ȱ
ȱ ȱ DZȱ ûȱ ȱ ȱ ȱ ãȱ w permi ȱ
w permi −1 ȱ ȱ a[ permi −1 ][ permi ] ȱ£ȱȱǰȱ ȱǽǾȱƽȱǽȬŗǾȱǰȱ
ȱȱ ȱȬ a[ permi −1 ][ permi ] Dzȱ
Ȭ
ǻǼDZȱ ȱ ȱ ȱ ǽǾǰȱ £ȱ £§ȱ ȱ ȱ
ȱȱȱȱȱ ȱ£ûDzȱ
ȱ
ûȱȱ¡ȱȱûȱȱȱ ȱûȱ ȱȱȱȱ
§ȱȱǯȱȱ ȱûȱȱȬǰȱȱȱȱ
ǽŖŜǾȱȱȱŗŝřȱȱǯȱȱ
78
Gundlegende Algorithmen mit Java
ȱ£ȱ ǰȱ ȱȱȱȱȱȱǻŗǰȱŘǰȱdzǰȱǼȱǯȱ
ȱ ȱ ȱȱDZȱ
ȱ
ȏ ȏǻǰȱǼȱ
ȱ ŗǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰ
ȱȱǀȱƸŗȱǻŗ≤ǀǼȱûǯȱ
ȱŘǯȱûȱȱȱȱȱȱȱȱȱȱ
ȱȱǰȱȱȱǁȱȱȱǻǀǼȱûǯȱǻȱȱȱȱ
ǰȱȱȱȱȱ£ǰȱȱ§ȱȱƸŗǼǯȱ
ȱřǯȱȱȱȱ ȱȱȱȱǯȱ
ȱŚǯȱȱȱȱ£ȱƸŗƸŘdzȱǯȱ
ȱȱȱȱȱȱȱȱǻǼȱ
ȏȱ ȏ ȏǻǰȱǼȱ
ȱ ȱ ȱȱ ȱ ¡ȱ ǰȱ ȱ ãđȱ ȱ ȱ Ȭ
ȱȱǯȱDZȱȱȱȱƽȱŜȱȱ ȱ ȱȱȱȱȬ
ȱǻŜǰȱřǰȱśǰȱŚǰȱŘǰȱŗǼȱǯȱȱȱȱȱȱȱȱǀȱƸŗȱȱŘȱǻ ȱřȱǀȱśȱȱ
ȱȱȱȱȱȱȱȱûǼǯȱ£ûȱȱƽȱŘȱȱ ŚȱƽȱŚȱ
ȱȱȱȱǰȱȱãđȱȱŘȱƽȱřȱǯȱȱȱȱŘȱȱŚȱ
ȱȱȱǻŜǰȱŚǰȱśǰȱřǰȱŘǰȱŗǼǯȱȱȱȱ£ǰȱȱȱȱŘȱȬ
ȱǻśǰȱřǰȱŘǰȱŗǼǰȱûȱđȱ£ȱǻŜǰȱŚǰȱŗǰȱŘǰȱřǰȱśǼǰȱȱ¡ȱȬ
ȱȱȱȱǻŜǰȱřǰȱśǰȱŚǰȱŘǰȱŗǼǯȱȱ
ȱ
ȱ£ ȱȱȱ¢ȱ£ȱǰȱȱ ȱȱȱ ǻǼǰȱȱ
ȱ ǮȬ §ȬȄȱ ǯȱ ȱ ȱ £ ȱ ȱ ȱ ȱ
ȱȱ ȱȱȱ ȱȱȱ£ ȱȱȱǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
4 Data Ordering Problem
79
ȱȱȱȱ ȱȱ ȱDZȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
3
ȱ
1
ȱ
ȱ
ȱ
2
ȱ
ȱ
ȱ
ȱ
ȱȱDZȱ
ȱ
ȏǻǰȱǼȱ
ȱ
ȱȱ¡ȱƜȱȱ
ȱ
ȱȱȱȱȱȱȱƜȱȱ
ȱ
ȱȱȱȱȱȱƜȱ¡ȱ
ȱ
ȏȱ ȏȱǻǰȱǼȱ
ȱ
ȱ
ȱȱ£ȱȱȱ¢ȱ£ǰȱ ȱ ȱȱȱ ǻǼǰȱ
ȱ ȱ ȱ £ ȱ ȱ £ȱ ȱ ȱ ȱ ǻđȱ ȱ ȱ Ǽȱ ǯȱ ȱ
ȱ£ȱȱȱȱȱ£DZȱ
ȱ
ȏǻǽǾǰȱǰȱǼȱ
ȱ
i + j −1
ȱ
ȱȱȱȱȱƜ
ȱ
ȱ
2
ȱ
ȱȱȱǻƜȱDzȱ≤ȱDzȱȱŗǼȱ
ȱ
ȱȱȱȱȱȱǻǽǾǰȱǽƸȬǾǼȱ
ȱ
ȏȱ ȏǻǽǾǰȱǰȱǼȱ
ȱ
ȱ
ȱȱȱȱȱ£ȱǽǯǯǾȱDZȱǽǾȱȱǽǾǰȱǽƸŗǾȱ
ȱǽȬŗǾǰȱǽƸŘǾȱȱǽȬŘǾǰȱǯǯǯȱȱđǰȱȱȱȱȱ £ȱȱƸȱ
ǰȱȱȱ ȱȱǽǾȱȱǽƸȬǾǯȱȱ
ȱ
80
Gundlegende Algorithmen mit Java
ȱãȱ ȱȱȬȱȱȱDZȱ
ȱ
ȏŘǻǽǾǰȱǰȱǼȱ
ȱ
ȱȱȱǻȱȱǀȱȱǼȱȱ
ȱ
ȱȱȱȱȱǻǽƸƸǾǰȱǽȬȬǾǼȱ
ȱ
ȱȱȏȱ
ȱ
ȏȱ ȏŘǻǽǾǰȱǰȱǼȱ
ȱ
ȱ
ȱ ȱ ¡ǻǼȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱǰȱ ȱȱȱǰȱȱȱȱȱȱȱȱ£ûǯȱȱȱ
ȱ Ȭȱ ǰȱ ȱ ȱ ȱ £ûǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ Ȭȱ ȱ ȱ ȱ ǻǼȱ ȱ ǻǼȱ
ǯȱ ȱ ǰȱ ȱ ȱ ȱ ¢ǯ¢¢ǻǼȱ ȱ ȱ ȱ ǯȱ
ȱ ǰȱȱȱȱ£ȱȱȱ¢ȱȱȱȱǯȱ
ȱ
ȱ ȱ ¡ǻǼȱ ȱ ȱ ȱ ãȱ ȱ ȱ £ãȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ §ȱ
ȱȱȱ£ȱȱȱȱȱãȱȱȱȱȱȱȱ
ȱȱȱǯȱȱ
ȱ
ȱ ȱ ¡ȱ ȱ ȱ £ȱ ǰȱ ûȱ ȱ ȱ ȱ
ȱ §ȱ ȱ ¢ǯȱ £ȱ ȱ ȱ ȱ ȱ ¡ȏǻǼǰȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ £ûǰȱ ȱ ȱ ȱ ǰȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ Ȭǰȱ ȱ ȱ ȱ ǽŖŜǾǰȱ ȱ
ŗŜŞǰȱȱ DZȱ
ȱ
ȱ ȏ ȏȱǻ¡Ȭŗǰȱ¡ȬŘǰȱdzǰȱ¡ŗǰȱ¡ŖǼȱ
ŗǯ ȱ←ȱȱȱ ¡ȱȱ¡ȱƽȱŖȱȱȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
Řǯ ȱǻ ¡ȱȱ¡Ǽȱȱ
ȱ
ȱ ¡ȱ ƽȱ Ŗǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱȱȱȱȱȱȱȱȱȱȱȱǻ←ŖDzȱǀDzȱȱŗǼȱ¡ȱ←ȱŖȱȱ
ȱ ȱ¡ȱ←ȱŗȱȱ¡ȱ←ȱŖȱûȱȱȱ≤ȱ
ȱ
Ȭŗǯȱȱ
ȱȱȱȱȱȱȱȱȱȱȱ¡ȱ←ȱŗȱ
ȱ
DZȱȱ
ȱ ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱǻŗŖŖŖŗŗŗǼƽŗŖŖŗŖŖŖȱǻƽřǼȱ
ȱ ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȃȱȱȱǷȄȱȱȱȱ
ȱ ȏȱ ȏ ȏȱǻ¡Ȭŗǰȱ¡ȬŘǰȱdzǰȱ¡ŗǰȱ¡ŖǼȱ
ȱ
¡ ǻǼȱȱȱȱãȱûȱȱ ȬǰȱȱȱȱȬ
ȱǻǰȱǼȱȱȱ ȱûǰȱȱȱȱȱȱǻȬ
ȱ Ǽȱȱȱȱǯȱȱǰȱ ȱȱȱȱǻǰȱǼȱǯȱ
ȱ
ȱ
4 Data Ordering Problem
81
ȱ ¢ȬȬȱ ȱ ȱ ȱ ȱ ȱ ǻǼȱ Ȭ
ǯȱȱ ȱȱȱ ȱȱ ȱǻŖǰȱŖǼȱȱȱȱ ȱ
ȱȱ£ûǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ
ȱȱȱȬǽǾǽǾȱûǯȱȱ
ȱ
if (isDOPI && k - a[i][j] < cost) {
i0 = i;
j0 = j;
cost = k - a[i][j];
}
ȱ
ȱ ȱ ãȱ ȱ ȱ £ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱǯȱȱȱ ¡ȱȱȱȱ ¡ǰȱȱ ȱ ȱȱȬ
ȱǽ ¡ƸŗǾȱǰȱûȱ ȱȱȱȱǰȱȱȱȱȱȱȱȱ
ǻȱǽŖǾȱȱǽ ¡ǾǼDZȱ
ȱ
boolean found = false;
for (int tmpIdx = 0; tmpIdx <= pIdx; tmpIdx++) {
if (p[tmpIdx] == i) {
found = true;
break;
}
}ȱ
ȱ
ȱȱƽȱȱȱǰȱȱȱȱȱȱȱȱȱȱǰȱȱ ȱûȬ
ȱȱ£ȱûȱȱȱ ȱûȱǽǾǯȱ
ȱ
if (found) {
if (a[j0][i] < aux) {
aux = a[j0][i];
next = i;
}
if (isDOPI && k - a[j0][i] < aux) {
aux = k - a[j0][i];
next = i;
}
}ȱ
ȱ
ȱȱãȱ ȱȱȱȱ¡ȱȱ ¡ȱȱȱȱ
ȱȱ¡ȱȱ ȱȱ ǰȱȱ ȱȱȱȱ DZȱ
ȱ
p[++pIdx] = next;
cost += aux;
82
Gundlegende Algorithmen mit Java
ûȱȱ ȱȱ Ȭȱȱȱȱȱȱȱǰȱ
ȱãDZȱ
if (isDOPI) {
boolean bLast = b.get(bIdx);
b.set(++bIdx, !(aux == a[j0][next])^bLast);
}ȱ
ȱ
ȱȱȱ£ȱȱȱȱǯȱȱ
ȱ
ȱ
ȱ£ȱ¡→ǰȱǽŖǾǽ¡Ǿ→ǰȱ→DZȱȱ
ȱȱDZȱ
ȱ
ȱ
if (a=b)
!(bLast^(aux==a[j0][next]))ȱȱ
res Ɯc
n res Ɯ!((a=b)^c)
ȱ
else res Ɯ!cȱȱ
ȱ§ȱ£DZȱ
ȱ
a b c a=b res (a=b)^c !((a=b)^c)
ȱ
0
0
0 0 0
1
1
if(aux==a[j0][next]){
1
1
0 0 1
1
0
b.set(++bIdx, bLast);
1
1
0 1 0
0
0
}else {
0
0
0 1 1
0
1
b.set(++bIdx, !bLast);
1
1
1 0 0
0
0
}ȱ
0
0
1 0 1
0
1
0
0
1 1 0
1
1
ȱ
1
1
1
1
1
1
0
ȱ
ȱ
ȱ
ȱ ȱ ǻǼȱ ȱ ȱ ¢Ȭȱ ȱ ǻ Ǽǰȱ ȱ ȱ
¢ȬȬȱ ȱ ǻ Ǽȱ §ȱ ǯȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ ǰȱ
ȱ ȱ ǰȱ ȱ ȱ ££ûǯȱ £ȱ ȱ ȱ ȱ ȱ ȱ
¢ȱ £ûǰȱ ȱ ȱ ȱ ȱ ǯȱ ǰȱ ȱ ȱ ȱ
ȱ ǰȱȱȱȱȱ ǯǰȱ ȱȱȱȱȱ ȱŜǯŖȱȱȱ
ȱ ǯȱ ȱ ȱ ȱ û£ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǻȱ ȱ ȱ Ǽȱ ȱ ȱ ǻȱ ȱ ȱ Ǽȱ
£ȱ ǯȱ ûȱ ȱ ûǰȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ
ȱȱ£ ȱȱ£ȱ ǯȱȱȱȱȱûȱǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
£ûǰȱ ȱȱȱȱȱȱȱȱȱ ǯȱ
ȱ
ȱ
ȱ
ȱ
4 Data Ordering Problem
83
¢ȱȱ
ȱ
ȱ
Ȧȱȱ
ȱ ȱ
ûȱȱȱ
ǻǼȱ
ǻǼȱ
ûȱȱȱ
ǻǼȱ
ǻǼȱ
ãȱȱȱ
ǻǼȱ
ǻǼȱ
ãȱȱȱ
ǻǼȱ
ǻǼȱ
ȱȱȱ
ǻǼȱ
ǻǼȱ
ȱȱȱ
ǻǼȱ
ǻǼȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ££ûǯȱ ȱ ȱ
ȱȱȱ ȱȱȱȱûȱȱǰȱȱȱ ȱȱ
ǯȱ ȱȱȱȱ ǰȱȱȱ£ûǯȱ
ȱ
ȱ ǻǼȱȱ ȱȱ£ȱ ȱȱ ȱȱȱ¡ȱȱ¢ȱ
¢ǀ ǁȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ¡ȱ ȱ ¢ȱ
¢ǀǁȱ£ǯȱȱȱȱ£ȱ£ȱ ȱȱŖȱȱŖȱȱ
£ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ãȱ £ǯȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱ¡ȱȱǻȱȱǼǰȱûȱ ȱȱãǰȱȱȱȱȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ £ûǯȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱ ȱȱȱȱ¡ȱȱȱȱ¡ǯȱđȱȱ ȱ¡ȱȱǰȱ
ȱ ȱȱ¡ȱȱȱȱȱȱ ȱûȱȱ ȱǯȱȱ
ȱ
ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱȱȱȬ £ǰȱȱȱȱȱȱ ȱȱ
ȱ Śȱ ȱ ¢Ȭ ǯȱ ȱ £ȱ ȱ ȱ ǰȱ ȱ ȱ ûȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ûȱ ȱ ȱ ǻǰȱ Ǽȱ ȱ ȱ
ȱûȱȱ ȱ ȬǽǾǽǾȱǯȱȱȱȱ Ȭȱ ȱ
ȱ §ǯȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ¢ȱ Ȭ
ǀ ǰȱǀǽǾǁǁȱȱȱ ȱ ȱȱ Ȭ ȱ Ȭ
ȱȱȱȱ ǻǼǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ £ȱ £ǯȱ ȱ ȱ ȱ
ȱ ȱ ȱ Ŝȱ £Ȭȱ ŗǰȱ Řǰȱ ǰȱ ŗǰȱ Řǰȱ ȱ ǯȱ ȱ
ȱȱȱ¢ȱȱ£ȱȱ£ǯȱ
ȱȱȱŗǰȱŘǰȱȱȱ ȱȱ£ȱȱȱãȱûȱȱ £ȱDZȱ
ŗȱȱŘȱȱȱ ȱǰȱȱȱȱȱȱȱ ǯȱ ȱ
§ȱȱȱȱȱ§ȱȱȱãDZȱŗȱȱŘȱȱȱ ȱûȱȱ§ȱ
ǰȱȱȱȱȱȱȱ ǯȱȱ§ ãȱ£ȱȱȱ
£§ǯȱ
84
Gundlegende Algorithmen mit Java
for(int n=n1; n<=n2; n+=sn)
for(int k=k1; k<=k2; k+=sk)dzȱȱȱȱȱȱȱȱȱȱȦȦȱûȱȱȱȱdzȱ
ȱ
ȱ ȱȱȱ£ȱȱDZȱ
ȱ
java P01_DOPI 5 8 1 25 65 20
ȱ
ǰȱȱȱȱȱǻȱȱ Ǽȱȱȱȱǯ¡ȱ
ȱȱȱDZȱ
n
k |
5
25 |
5
45 |
5
65 |
6
25 |
6
45 |
6
65 |
...
RAN
48
90
134
66
114
158
DOP
EX
40
79
117
55
95
146
GMS
41
84
120
55
98
155
GM
40
79
117
55
95
146
DOPI
LB | RAN
EX
37 | 61
35
79 | 91
76
117 | 134 116
55 | 58
47
95 | 121
86
142 | 167 136
GMS
38
79
118
47
88
139
GM
35
76
116
47
86
136
LB
34
76
115
47
84
136
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǻǼȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱ ǰȱȱȱȱ¡ǰȱ §ȱȱ£ȱǯȱ
ȱȱ ȱȱȱûȱȱ£ȱȱȱãǯȱȱ
Programm
import java.io.*;
import java.util.*;
public class P01_DOPI {
private int n;
private int k;
private BitSet w[];
private int a[][];
private int p[];
private BitSet b;
/////////////////////////////////////////////////////
P01_DOPI(int n, int k) {
this.n = n;
this.k = k;
// Wörter generieren
Random random = new Random();
this.w = new BitSet[n];
for (int i = 0; i < n; i++) {
BitSet wAux = new BitSet(k);
for (int j = 0; j < k; j++) {
4 Data Ordering Problem
wAux.set(j, random.nextBoolean());
}
w[i] = wAux;
}
// Aufbau der Matrix
this.a = new int[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
a[i][j] = hammingDist(w[i], w[j], k);
}
// Initialisierung der Permutation und des BitStrings
this.p = new int[n];
this.b = new BitSet(n);
for(int i=0; i<n; i++){
p[i]=i;
b.set(i, false);
}
}
/////////////////////////////////////////////////////
private static int hammingDist(BitSet w1, BitSet w2,
int size) {
int t = 0;
for (int i = 0; i < size; i++)
if (w1.get(i) != w2.get(i))
t++;
return t;
}
/////////////////////////////////////////////////////
private void shufflePermutation() {
for (int idx = p.length - 1; idx > 0; idx--) {
// Wähle einen beliebigen Index zwischen 0 und idx
int randLoc = (int) (Math.random() * (idx + 1));
int temp = p[randLoc];
p[randLoc] = p[idx];
p[idx] = temp;
}
}
/////////////////////////////////////////////////////
private int getCostDOP(int perm[]) {
int t = 0;
for (int i = 1; i < n; i++)
t += a[perm[i - 1]][perm[i]];
return t;
}
85
86
Gundlegende Algorithmen mit Java
/////////////////////////////////////////////////////
int getRandomCostDOP() {
for (int i = 0; i < n; i++)
p[i] = i;
this.shufflePermutation();
return getCostDOP(p);
}
/////////////////////////////////////////////////////
private int getCostDOPI(int perm[], BitSet bs) {
if (this.n <= 1)
return 0;
int t = 0;
for (int i = 1; i < n; i++)
t += (bs.get(i) == bs.get(i - 1)) ?
a[perm[i - 1]][perm[i]] :
k - a[perm[i - 1]][perm[i]];
return t;
}
/////////////////////////////////////////////////////
int getRandomCostDOPI() {
this.b.clear();
Random rand = new Random();
for (int i = 0; i < n; i++) {
p[i] = i;
this.b.set(i, rand.nextBoolean());
}
this.shufflePermutation();
return getCostDOPI(p, b);
}
/////////////////////////////////////////////////////
private static void swap(int arr[], int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/////////////////////////////////////////////////////
private static void reverse(int arr[], int i, int j) {
int half = (i + j - 1) / 2;
for (int k = i; k <= half; k++) {
swap(arr, k, i + j - k);
}
}
4 Data Ordering Problem
///////////////////////////////////////////////////////
private static boolean nextPermutation(int[] arr) {
int k = arr.length - 2;
while (k >= 0 && arr[k] > arr[k + 1])
k--;
if (k >= 0) {
int t = arr.length - 1;
while (arr[t] < arr[k])
t--;
swap(arr, k, t);
reverse(arr, k + 1, arr.length - 1);
return true;
} else {
return false;
}
}
/////////////////////////////////////////////////////
int getExactDOP() {
int[] r = new int[n];
for (int i = 0; i < n; i++){
r[i] = i; p[i]=i;
}
int t = getCostDOP(p);
while (nextPermutation(r)) {
int aux = getCostDOP(r);
if (aux < t) {
t = aux;
System.arraycopy(r, 0, p, 0, n);
}
}
return t;
}
/////////////////////////////////////////////////////
private static boolean nextBitSet(BitSet bs, int numBits) {
int clearBit = bs.nextClearBit(0);
if (clearBit < numBits) {
bs.set(clearBit);
bs.clear(0, clearBit);
return true;
} else {
return false;
}
}
87
88
Gundlegende Algorithmen mit Java
/////////////////////////////////////////////////////
int getExactDOPI() {
int[] r = new int[n];
for (int i = 0; i < n; i++){
r[i] = i; p[i]= i;
}
b.clear();
int t = getCostDOPI(p, b);
while (nextPermutation(r)) {
BitSet bs2 = new BitSet(n);
do {
int aux = getCostDOPI(r, bs2);
if (aux < t) {
t = aux;
System.arraycopy(r, 0, p, 0, n);
b.clear();
b.or(bs2);
}
} while (nextBitSet(bs2, n));
}
return t;
}
/////////////////////////////////////////////////////
int getGMS(boolean isDOPI) {
int pIdx = -1;
b.clear();
int bIdx = -1;
int i0 = 0, j0 = 1;
int cost = a[i0][j0];
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++) {
if (a[i][j] < cost) {
i0 = i;
j0 = j;
cost = a[i0][j0];
}
if (isDOPI && k - a[i][j] < cost) {
i0 = i;
j0 = j;
cost = k - a[i0][j0];
}
}
p[++pIdx] = i0;
p[++pIdx] = j0;
if (isDOPI) {
b.clear(++bIdx);
4 Data Ordering Problem
89
b.set(++bIdx, a[i0][j0] != cost);
}
while (pIdx < n - 1) {
int next = -1;
int aux = k + 1;
for (int i = 0; i < n; i++) {
boolean found = false;
for (int tmpIdx = 0; tmpIdx <= pIdx; tmpIdx++) {
if (p[tmpIdx] == i) {
found = true;
break;
}
}
if (found) {
if (a[j0][i] < aux) {
aux = a[j0][i];
next = i;
}
if (isDOPI && k - a[j0][i] < aux) {
aux = k - a[j0][i];
next = i;
}
ȱ£DZȱ
if (isDOPI){
}
b.set(bIdx+1,
}
!(aux == a[j0][next])^bLast);
p[++pIdx] = next;
bIdx++;
cost += aux;
}
if (isDOPI) {
boolean bLast = b.get(bIdx);
b.set(++bIdx, !(aux == a[j0][next])^bLast);
}
j0 = next;
}
return cost;
}
/////////////////////////////////////////////////////
int getGM(boolean isDOPI) {
b.clear();
Deque<Integer> pAux = new ArrayDeque<Integer>();
Deque<Boolean> bAux = null;
bAux = new ArrayDeque<Boolean>();
int i0 = 0, j0 = 1;
int cost = a[i0][j0];
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++) {
if (a[i][j] < cost) {
i0 = i;
j0 = j;
90
Gundlegende Algorithmen mit Java
cost = a[i0][j0];
}
if (isDOPI && k - a[i][j] < cost) {
i0 = i;
j0 = j;
cost = k - a[i0][j0];
}
}
pAux.addLast(i0);
pAux.addLast(j0);
if (isDOPI) {
bAux = new ArrayDeque<Boolean>();
bAux.addLast(false);
bAux.addLast(a[i0][j0] != cost);
}
while (pAux.size() < n) {
int next = -1;
int aux = k + 1;
for (int i = 0; i < n; i++) {
Integer iObj = null;
for (Integer itPAux : pAux) {
if (itPAux.intValue() == i) {
iObj = itPAux;
break;
}
}
if (iObj == null) {
if (a[j0][i] < aux) {
aux = a[j0][i];
next = i;
}
if (a[i0][i] < aux) {
aux = a[i0][i];
next = i;
}
if (isDOPI && k - a[j0][i] < aux) {
aux = k - a[j0][i];
next = i;
}
if (isDOPI && k - a[i0][i] < aux) {
aux = k - a[i0][i];
next = i;
}
}
}
cost += aux;
if (a[j0][next] == aux ||
4 Data Ordering Problem
(isDOPI && k - a[j0][next] == aux)) {
pAux.addLast(next);
if (isDOPI) {
bAux.addLast(!(aux == a[j0][next])^bAux.getLast());
}
j0 = next;
} else {
pAux.addFirst(next);
if (isDOPI) {
bAux.addFirst(
!(aux == a[i0][next])^ bAux.getFirst() );
}
i0 = next;
}
}
Iterator<Integer> pAuxIt = pAux.iterator();
for (int i = 0; i < n; i++) {
p[i] = pAuxIt.next();
}
if (isDOPI) {
Iterator<Boolean> bAuxIt = bAux.iterator();
for (int i = 0; i < n; i++) {
b.set(i, bAuxIt.next());
}
}
return cost;
}
/////////////////////////////////////////////////////
private static void putInMultimap(
TreeMap<Integer, List<int[]>> mmap,
Integer key,
int[] value ) {
List<int[]> values = mmap.get(key);
if (values == null) {
values = new ArrayList<int[]>();
mmap.put(key, values);
}
values.add(value);
}
/////////////////////////////////////////////////////
private static class TreeMultimapIterator {
private Iterator<Map.Entry<Integer, List<int[]>>> mmapIt;
private ListIterator<int[]> currValuesIt;
private int[] currValue;
91
92
Gundlegende Algorithmen mit Java
Map.Entry<Integer, List<int[]>> currEntry;
TreeMultimapIterator(TreeMap<Integer, List<int[]>> mmap) {
this.mmapIt = mmap.entrySet().iterator();
}
boolean next() {
if ( this.currValuesIt != null &&
this.currValuesIt.hasNext() ) {
this.currValue = this.currValuesIt.next();
return true;
} else if (mmapIt.hasNext()) {
this.currEntry = this.mmapIt.next();
this.currValuesIt =
this.currEntry.getValue().listIterator();
this.currValue = this.currValuesIt.next();
return true;
} else {
return false;
}
}
Integer key() {
return this.currEntry.getKey();
}
int[] value() {
return this.currValue;
}
void remove() {
this.currValuesIt.remove();
if (this.currEntry.getValue().isEmpty()) {
this.currValuesIt = null;
this.mmapIt.remove();
}
}
}
/////////////////////////////////////////////////////
int getLB(boolean isDOPI) {
int cost = 0;
TreeMap<Integer, List<int[]>> E =
new TreeMap<Integer, List<int[]>>();
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n; j++) {
int[] e = {i, j};
4 Data Ordering Problem
93
putInMultimap(E, a[i][j], e);
if (isDOPI)
putInMultimap(E, k - a[i][j], new int[]{i,j});
}
int C[] = new int[n];
for (int i = 0; i < C.length; i++)
C[i] = i;
TreeMap<Integer, List<int[]>> H =
new TreeMap<Integer, List<int[]>>();
int szH = 0;
while (szH < n - 1) {
TreeMultimapIterator it = new TreeMultimapIterator(E);
it.next();
int uu = it.value()[0];
int vv = it.value()[1];
while (C[uu] == C[vv]) {
it.next();
uu = it.value()[0];
vv = it.value()[1];
}
putInMultimap(H, it.key(), it.value());
szH++;
cost += it.key();
it.remove();
int mi = Math.min(C[uu], C[vv]);
int ma = Math.max(C[uu], C[vv]);
for (int i = 0; i < n; i++)
if (C[i] == ma)
C[i] = mi;
}
return cost;
}
/////////////////////////////////////////////////////
public static void main(String args[]) throws IOException {
if (args.length != 6) {
throw new IOException(
"Invalid number of parameters ! Required: 6; Provided: "
+ args.length);
}
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
int sn = Integer.parseInt(args[2]);
int k1 = Integer.parseInt(args[3]);
int k2 = Integer.parseInt(args[4]);
int sk = Integer.parseInt(args[5]);
PrintStream out = new PrintStream(new File("report.txt"));
94
Gundlegende Algorithmen mit Java
try {
out.printf("%25s%35s%n", " DOP", " DOPI");
out.printf("%5s%5s |%5s%5s%5s%5s%5s ||%5s%5s%5s%5s%5s%n",
"n", "k",
"RAN", "EX", "GMS", "GM", "LB",
"RAN", "EX", "GMS", "GM", "LB");
for (int n = n1; n <= n2; n += sn) {
for (int k = k1; k <= k2; k += sk) {
int kk = 3;
while(kk-->0){
P01_DOPI dopi = new P01_DOPI(n, k);
out.printf("%5d%5d |", n, k);
out.printf("%5d%5d%5d%5d%5d ||",
dopi.getRandomCostDOP(),
dopi.getExactDOP(), dopi.getGMS(false),
dopi.getGM(false), dopi.getLB(false));
out.printf("%5d%5d%5d%5d%5d%n",
dopi.getRandomCostDOPI(),
dopi.getExactDOPI(), dopi.getGMS(true),
dopi.getGM(true), dopi.getLB(true));
}}
}
} finally {
out.close();
}
}
}
Auswertung der Ergebnisse
ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭȱ Ȭȱ Ȭǰȱ Ȭȱ ȱ Ȭȱ
ȱûȱȱǰȱȱȱȱȱȱȱȱśȱŝȱŗȱŘŖŖȱŜŖŖȱŘŖŖȱ
ǯȱ
n
5
5
5
6
6
6
7
7
7
ȱ
ȱȦ ȱûȱȱȱ
ȱ
DOP
DOPI
k | RAN
EX GMS
GM
LB || RAN
EX GMS
GM
LB
200 | 390 373 374 373 372 || 399 371 373 371 370
400 | 779 753 774 773 752 || 792 740 752 743 739
600 | 1145 1133 1183 1133 1127 || 1148 1090 1100 1094 1076
200 | 530 480 488 482 479 || 513 449 454 449 447
400 | 1013 950 963 960 950 || 1006 935 943 941 931
600 | 1478 1442 1444 1442 1436 || 1488 1428 1444 1428 1428
200 | 604 547 547 547 545 || 580 534 539 534 533
400 | 1197 1152 1169 1163 1151 || 1190 1121 1132 1121 1119
600 | 1778 1718 1735 1722 1717 || 1785 1699 1707 1699 1697
4 Data Ordering Problem
95
ȱ ȱ ȱ ȱ Ȭȱ ȱ Ȭȱ ûȱ ȱ £ȱ ȱ
ȱȱȬǰȱȱȱȱǰȱȱãđȱȱ ǯȱȱȱȱȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ǰȱ ȱ ȱ ȱ ȱ ǯȱ đȱ ȱ ǰȱ ȱ ȱ ȱ
ȱȱȱȱ ȱǯȱ
ûȱđȱȱȱ§ȱȱȱȱǰȱȱȱ ȱȱȱ§ȱȱȱ
ǯȱȱȱ£ȱǰȱȱ ȱȱȱǰȱȱȱȱȱŗŘśŖǰȱŗŚśŖǰȱ
ǯǯǯǰȱ ŘŖśŖȱ ȱ ȱ ȱ ȱ ȱ ŗśǰȱ řŗśȱ ȱ Ŝŗśǯȱ đȱ ȱ ȱ ȱ Ȭ
ȱȱǰȱ ȱȱ£ȱȱȱ ûǯȱȱûȱȱȱ
∆ȱ ǰȱ ȱ £ǰȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱȱȱȱȱȱ£ȱǯȱ
ȱȱ
ȱ
ȱȱ
ȱ
ȱ
1250
15
1250 315
1250 615
1450
15
1450 315
1450 615
1650
15
1650 315
1650 615
1850
15
1850 315
1850 615
2050
15
2050 315
2050 615
ȱ
ȱ
9341
196999
383842
10868
228241
445842
12363
259686
507187
13915
291342
568827
15277
322854
630214
ȱ
2480
163523
337871
2766
189220
391117
3031
214691
444244
3315
239950
497320
3570
265499
550324
ȱ
2478
163535
337861
2755
189217
391146
3041
214698
444233
3314
239984
497371
3588
265533
550376
∆ȱ
-2
+12
-10
-11
-3
+29
+10
+7
-11
-1
+34
+51
+18
+34
+52
ȱ
2102
160951
334211
2342
186318
386907
2582
211377
439538
2890
236325
492047
3025
261566
544575
ȱ
ȱȱȱȱȱȱ ¢Ȭȱ ȱȱȬ
ǰȱȱûȱȱǯȱđȱȱ ǰȱȱȱ ¢ȬȱȱȬȱ
ȱ§ȱǰȱȱȱ ǰȱȱȱ ¢Ȭȱȱȱȱȱ¡Ȭ
ȱȱǯȱ ȱȱŜȱȱŗśȱ§ȱȱ ȱȱȱ ǯȱ
ȱ
ȱ
96
Gundlegende Algorithmen mit Java
ȱ ȱ
ȱ
ȱ
ȱȱ
∆ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
2083
1250
15
9372
2087
+4
1709
161427
1250 315
196813
161481
+44
159040
334411
1250 615
384281
334452
+41
330858
2308
1450
15
54189
2315
+7
1803
186626
1450 315
228251
186702
+76
183975
387106
1450 615
445764
387119
-13
383004
2513
1650
15
12295
2522
-9
1889
211933
1650 315
259779
211935
-2
208841
439712
1650 615
506744
439734
+22
435103
2741
1850
15
13836
2750
-9
1969
237099
1850 315
291321
237102
+3
233542
492231
1850 615
568973
492307
+76
487102
2950
2050
15
15366
2952
-2
1975
262273
2050 315
322770
262282
+9
258412
544788
2050 615
260096
544804
+16
539004
ȱ ȱ ȱ ȱ ȱ ȱ śȱ ȱ ŗśȱ §ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ǰȱȱȱȱȱȱȱȱǯȱȱȱȱȱȱ
ȱȱȱǰȱȱȱȱǯȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
śǯ
Ŝǯ
ŝǯ
ȱȱȱȱȱûǵȱȱ
ȱ ȱ ȱ Ȭȱ ȱ ȱ Ȭ£ȱ ǻȬ£ǰȱ ȱ
ǯȱŞǯȱ¢ȱǰȱȱŗřǼȱȱ ȱǰȱȱ
ȱȱȱǯȱ
ȱȱȱȱȱ ǰȱ ȱȱȱȱǯȱ
ȱȱ££¡ȱ¢ȱ£ȱ ȱǰȱȱȱȬ
ȱ ȱ ȱ ǰȱ ȱ ȱ ǰȱ ȱ ȱ ȱ §ȱ ȱ
¡ȱ £ȱ ǯȱ £ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ¡ȱ ȱ
ȱ¢ȱȱǻȬŗǼȱƸȱǻȬŘǼȱƸȱdzƸŗȱƽȱǻȬŗǼȦŘȱȱȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱ
£ȱȱȱȱȱǻǼȱȱȬ
ǻǼȱ£ȱȱȱǻȱ Ǽǯȱȱȱ
ȱûȱȱȱ¡ǻǼȱȱ¡ ǻǼǯȱ
ȱȱȱȱǰȱȱȱȱȱȱDZȱȱ
ȱ ãǰȱ ȱ ££¡ǰȱ ȱ ȱ ȱ ûȱ ȱ
ȱûȱȱȱȱȱȱǻǰȱǼǯȱ
4 Data Ordering Problem
97
Şǯ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱ£§£ȱȱ£ȱȱȱǯȱ
şǯ ȱȱȱȬȱȱ ȱȱȱȱǰȱȱ
ȱȱȱ£ǯȱ
ŗŖǯ ȱȱȱûȱãđȱ £ȱǻđȱȱȱǼǯȱ
ŗŗǯ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
§ȱȱȱ¡ȱȱȱȱȬȱ
ǯȱDZȱȱ
ȱ
Tastatur
perm.out
ȱ
3
1 2 3
ȱ
1 3 2
2 1 3
ȱ
2 3 1
ȱ
3 1 2
ȱ
3 2 1
ȱ
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ¡Ȭ
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ûȱ ȱ Ȭ
ûȱȱǵȱ
ŗŘǯ ȱȱȱǰȱȱȱȱȱȱ§ȱȱȱ¡Ȭ
ȱ ȱ ȱ ȱ ȱ Ȭȱ ǯȱ
DZȱȱ
ȱ
Tastatur
bitstrings.out
2
00
ȱ
01
ȱ
10
ȱ
11
ȱ
£ȱȱȱȱǰȱȱȱȱ¡ȱȬ
ǯȱȱȱȱȱûȱȱûȱȱǵȱ
ŗřǯ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ £ǯȱ
£ȱȱȱȱȱȱȱǻȱ Ǽǰȱȱ££ǰȱ
ȱȱȱȱȱȱ ȱǯȱ
ŗŚǯ ȱȱȱȱǮȬȃȱ ǰȱȱȱȱ ȱśȱûȱ
ǯȱȱȱȱȱȱȱȱȱȱȱȬ
ȱȱȱ ǯȱ
ŗśǯ ȱ ȱ ǯǯȱ ȱ ȱ ȱ ȱ ǻǼǰȱ
ǻǼȱȱǻǼǰȱȱȱ £ȱǯȱ£ȱȱȱȬ
ȱȱ ȱȱȱȱȱȱȱȱȬ
ȱȱǻǼǰȱ ǻǼȱȱǻǼǯȱ
ŗŜǯ ȱȱȱǻǼȱ£ȱ ȱûȱȱȬ £ǰȱȱȱȬ
ȱȱǰȱȱȱǰȱȱȱȱ ȱ¡£ȱȱǽǾȱ
98
Gundlegende Algorithmen mit Java
ȱ ǯȱȱ ȱȱȱȱûȱȱ ȱȱ ȱ
ȱȱȱ ȱǻ ¢Ǽȱȱǻ ȱȱǽŘǾǼǯȱ ȱȱȱ
ȱȱ ȱȱȱ ȱDZȱ
TreeMap<Double, List<Integer>> H =
new TreeMap<Double, List<Integer>>();
ŗŝǯ ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ Ŝȱ
£ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
Ȭ Ȭȱȱȱȱȱȱȱ ȱ
ȱȱȱ ȱ¢ǯȱ
ŗŞǯ ¢ȱ ȱ ȱ ¢Ȭ ȱ ǻȱ §ȱ ãđǼȱ ȱ
ȱ
ǯȱ
ȱ
ȱ
¢ȱ
ȱ
ȱ
£§§ǰȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ
Ȭǯȱȱ ȱ¢ȱȱȱȱǯǯǰȱ ȱȱȱ
ȱ ȱ ȱ ȱ ȱ ǯǯǰȱ ȱ ȱ ȱ ȱ
ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ §ǯȱ ȱ
ãȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ Ȭȱ ǻ£ ǯȱ
ȬǼȱ ȱ £§ȱ ǯȱ ȱ ȱ ȱ ȱ
ȱ ¢ȱ ûȱ ȱ ǻ£ ǯȱ Ǽȱ ȱ đȱ ȱ ȱ ǻ£ ǯȱ
Ǽȱûǯȱȱ£ȱȱ£ȱȱãȱ
ȱȱ¢ǯǻǼȱȱȱȱȱǯȱ
ȱ
ȱȱȱ
5
Rekursion
ȱ
Vollständige Induktion
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ûȱ ȱ ȱ ǰȱ ȱ ûȱ
ǯȱ ȱ ûȱ ȱ Wȱ ȱ ȱ
ȱ ǯȱ ȱ ȱ ȱ ûȱ Wȱ £ȱ
ǰȱȱȱȱȱȱûȱȱ
ûȱȱ ǰȱ ȱȱ£ȱȱ
ȱ§ǯȱȱ
Giuseppe Peano
(1858-1932)
ȱ ȱ ȱ ȱ ȱ Wȱ ȱ ûȱ
ȱ ¡ȱ ȱ ȱ śȱ §£ȱ ȱ
ȱ ȱ
ȱ ȱȱ
ȱǻȱ¡ǼDZȱ
ȱ
ȱ DZȱȱ
ȱ DZȱȱ
Ŗȱȱȱûȱǯȱȱ
ȱûȱȱȱȱȱȱǰȱȱȱȱûȬ
ȱȱǯȱȱ
ȱ DZȱȱ Ŗȱȱȱȱûȱȱ
ȱ DZȱȱ ȱȱûȱȱȱȱȱ
ȱDZȱ
ǻ ¡ǼDZȱ ȱ ȱ ȱ §ȱ ȱ ûȱ ǰȱ ȱ ȱ
ȱȱŖȱȱȱȱûȱȱȱȱȱȱ§ǯȱ
ȱ ¡ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ Ȭ
§ȱ ǯȱȱ§ȱ ȱǻǮȱȱȱȱƸŗȃǼȱ ȱ
ȱ ǰȱȱȱûȱûȱȱ£ȱ ǯȱȱȱ ȱ
ȱûȱȱ§ȱ£ȱ ǯȱ
100
Grundlegende Algorithmen mit Java
ȱȱȱ§ȱ DZȱ
ȱ ȱǻȱŗǼDZȱȱ£ȱǰȱȱȱȱûȱȱȬ
ȱǻ£ǯȱǯȱûȱƽŖȱȱƽŗǼȱ ȱǯȱ
£ȱ ȱǻȱŘǼDZȱȱȱȱǰȱȱȱȱǻǼȱ
ûȱȱûȱȱȱȱWȱ ȱǯȱȱ
ȱ ȱǻȱřǼDZȱȱȱȱ£ǰȱȱȱǻƸŗǼȱûȱǰȱ
ȱǻǼȱ ȱǯȱȱȱȱȱ£ǰȱȱȱǰȱȱûȱȱ
ǰȱȱûȱȱȱǯȱȱ
ȱ đȱǰȱȱȱ
ǻŖǼȱ ȱ ȱ ǻȱ ŗǼȱ ȱ ȱ ȱ Ǯ ȱ ǻǼǰȱ ȱ ǻƸŗǼȃȱ ȱ ȱ
ǻȱřǼǯȱ
ȱǰȱȱȱȱȱûȱȱûȱȱǯȱȱȱȱ
ûȱȱŖȱ ȱȱȱȱȱȱȱȱȱûȱȱŗȱ£Ȭ
ǰȱûȱȱŘȱǰȱ ǯȱ
ȱDZȱ
•
•
•
ȱ ȱȱȱȱ ȱ£ȱǰȱȱȱ Ȭ
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
ȱ ǯȱ ȱ ȱ Ȯȱ ûȱ ȱ
ǯȱ
ȱȱȱȱƽŖȱǯȱȱȱǰȱȱȱûȱȱãđȱ
Ŗȱ £ȱ ǯȱ ûȱ ȱ ȱ ȱ ǻǼȱ ȱ ȱ
ãȱȱǯȱȱȱȱȱ§ȱǯȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ đȱ ǯȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ûǰȱ ȱ ȱ ûȱ ȱ Ȭ
§ȱ ȱ ȱ ǯȱ
n
ȱȱŗǯȱǯȱȱǰȱȱ
¦ k (k + 1) = n + 1 ȱûȱȱȱ≥ȱŗǯȱȱȱȱȱ
1
n
ǻŗǼȱ
k =1
ȱ ǯȱ ȱ ȱ ãȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ¡DZȱ
5
Rekursion
n
101
n
1
1 · 1 1 1 1
1
1
1
n
§1
ǯȱ
=
=1−
=
¨ −
¸ = − + − + ... + −
k (k + 1) k =1 © k k + 1 ¹ 1 2 2 3
n n +1
n +1 n +1
k =1
¦
¦
÷ȱ
ȱ ȱ §ȱ ǯȱ ȱ £ȱ ȱ ǻǼȱ ȱ ȱ
n
¦ k (k + 1) = n + 1 ȱȱûȱ ǰȱȱȱ ȱȱûȱȱȱ≥ȱŗǯȱȱ
1
n
k =1
ȱǻ ǼDZȱǻŗǼȱȱ DZȱ
1
1
= ǯȱ
1⋅ 2 2
n
£ȱǻ ǼDZȱǻǼDZȱȱ
1
n
¦ k (k + 1) = n + 1 ȱȱ ǯȱ
k =1
ȱǻ ǼDZȱȱûȱ£ǰȱȱǻƸŗǼȱȱ ȱǯȱ
ȱ ȱ ǻƸŗǼȱ DZȱ
n +1
n +1
1
¦ k (k + 1) = n + 2 ǯȱ ȱ ȱ £ȱ ȱ ȱ ȱ
k =1
ȱ DZȱ
n +1
1
1
n
1
1
n
¦ k (k + 1) = (n + 1)(n + 2) + ¦ k (k + 1) = (n + 1)(n + 2) + n + 1 =
k =1
ȱ
k =1
1 + 2n + n 2
(n + 1) 2
n +1
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ =
=
=
ǯȱ
(n + 1)(n + 2) (n + 1)(n + 2) n + 2
§đȱȱ£ȱȱ§ȱ ȱǰȱȱȱȱǻǼȱûȱȱ
ûȱȱȱȱȱ≥ȱŗȱ ȱǯȱȱ÷ȱ
ȱ Řǯȱ ȱ ȱ ȱ £ǯȱ ȱ ǰȱ ȱ ȱ ȱ Ǯ ȱ ȱ ȱ
£ȱȱȱȱûȱǰȱȱȱ n
p
− n ȱȱȱȃȱ ȱǯȱ
ȱȱ§ȱ DZȱȱ£ȱȱȱȱǻǼǯȱȱ
ȱǻ ǼDZȱǻŖǼȱȱǻŗǼȱȱ DZȱ n p − n ƽŖȱȱŖȱȱȱȱǯȱ
£ȱǻ ǼDZȱǻǼDZȱǮ n p − n ȱȱȱȃȱȱ ǯȱ
102
Grundlegende Algorithmen mit Java
ȱǻ ǼDZȱȱûȱ£ǰȱȱȱǻƸŗǼȱ ȱǯȱ
ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ( n + 1) p − ( n + 1) ȱ ȱ ȱ Ȭ
ȱDZȱ
§ p·
§ p·
§ p ·
¸¸n + 1) − (n + 1) = ȱ
(n + 1) p − (n + 1) = (n p + ¨¨ ¸¸ n p−1 + ¨¨ ¸¸n p−2 + ... + ¨¨
©1¹
©2¹
© p − 1¹
§ p·
§ p·
§ p ·
¸¸n ǯȱȱȱȱȱȱȱȱȱȱȱȱȱȱ ȱ
= (n p − n) + ¨¨ ¸¸ n p−1 + ¨¨ ¸¸n p−2 + ... + ¨¨
©1¹
©2¹
© p − 1¹
§ p· § p·
ȱ
ȱ
ȱȱȱȱǻŘǼȱ
§ p ·
¸¸ ȱȱȱȱǯȱȱ
ȱȱȱǰȱǰȱȱȱȱ ¨¨ ¸¸ ǰȱ ¨¨ ¸¸ ǰȱdzǰȱ ¨¨
©1¹ ©2¹
© p − 1¹
ȱ £ȱ ȱ ǰȱȱȱ n − n ȱȱȱȱǯȱȱ
ȱȱȱȱ£ȱȱȱȱǻŘǼȱȱȱǰȱȱǻƸŗǼȱȱ
ǯȱ
p
§đȱȱ£ȱȱ§ȱ ȱǰȱȱȱȱǻǼȱûȱȱ
ûȱȱ ȱǯȱ÷ȱ
ȱřǯȱȱ¢Ȭ £Ȭȱǻ £ȱǼǯȱȱȱȱ
ȱ û£ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
DZȱȱȱǻǼǰȱ¢ȱǻȱǼǰȱȬ
ǰȱ ȱȱǯȱȱŗǰȱŘǰȱdzǰȱǰȱŗǰȱŘǰȱdzǰȱȱȱȱǰȱ
ȱȱûȱȱûȱȱȱ≥ȱŗDZȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ (a12 + a22 + ... + an2 )(b12 + b22 + ... + bn2 ) ≥ (a1b1 + a2 b2 + ... + an bn ) 2 ǯȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻřǼȱ
ȱ
ȱ ǯȱȱ ȱ ȱȱȱãȱ ȱǰȱȱȱ ȱ
ȱ ȱ £ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ¡DZȱ
ȱ
(a1 x + b1 ) 2 + (a2 x + b2 ) 2 + ... + (an x + bn ) 2 = 0 ȱ ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŚǼȱ
ȱ
ȱ ȱǻŚǼȱȱ¡ȱȱ£ȱǻȱȱȱȱ £ȱȱ
ȱãđȱȱȱŖȱûȱȱȱȱ¡Ǽȱȱãȱȱȱ§Ȭ
ȱȱȱ DZȱ
5
Rekursion
103
(a12 + a22 + ... + an2 ) x 2 + 2(a1b1 + a2b2 + ... + an bn ) x + (b12 + b22 + ... + bn2 ) = 0 ǯȱȱȱȱȱȱȱȱȱȱȱ ǻśǼȱ
ȱ
ȱȱȱ ȱ¡ȱȱ£ȱǰȱȱȱȱȱ
ȱȱȱŖDZȱ
ȱ
D = 4(a1b1 + a2b2 + ... + an bn ) 2 − 4(a12 + a22 + ... + an2 )(b12 + b22 + ... + bn2 ) ≤ 0 ȱȱȱȱȱȱȱȱȱȱ ǻŜǼȱ
ȱ
ȱǻŜǼȱȱ§ȱ£ȱǻřǼǯȱ÷
ȱ
ȱȱ§ȱ ǯȱȱ£ȱǻřǼȱȱǻǼǯȱȱ
ȱǻ ǼDZȱǻŗǼȱȱ DZȱ a12 b12 ≥ (a1b1 ) 2 = a12b12 ȱûȱȱŗǰȱŗȱ∈ȱ[ǯȱ
£ȱǻ ǼDZȱǻǼȱȱ ǯȱ
ȱǻ ǼDZȱȱûȱ£ǰȱȱǻƸŗǼȱȱ ȱǯȱ
ǻƸŗǼDZȱ (a12 + a22 + ... + an2+1 )(b12 + b22 + ... + bn2+1 ) ≥ (a1b1 + a2 b2 + ... + an +1bn +1 ) 2 ȱ
ȱ
­°(a12 + a22 + ... + an2 )(b12 + b22 + ... + bn2 ) + an2+1 (b12 + b22 + ... + bn2 ) +
⇔ȱ ®
°̄+ bn2+1 (a12 + a22 + ... + an2 ) + an2+1bn2+1 ≥ (a1b1 + a2b2 + ... + an+1bn+1 ) 2
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŝǼȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱ £ȱDZȱȱ
ȱ
a12 + a22 + ... + an2 ⋅ b12 + b22 + ... + bn2 ≥ a1b1 + ... + anbn ȱ
ȱ 2an +1bn +1 ( a1b1 + ... + anbn ) ≤ 2an +1bn +1 a12 + a22 + ... + an2 ⋅ b12 + b22 + ... + bn2 ≤ ȱ
an2+1 (b12 + ... + bn2 ) + bn2+1 ( a12 + ... + an2 )
ȱ
ȱ
ȱȱȱ
ǻŞǼ
£ȱȱȱ
ȱ
2 xy ≤ x 2 + y 2 für alle x, y ∈ [
(n ( x − y ) 2 ≥ 0 )
(a12 + a22 + ... + an2 )(b12 + b22 + ... + bn2 ) ≥ (a1b1 + a2b2 + ... + an bn ) 2
an2+1 (b12 + ... + bn2 ) + bn2+1 (a12 + ... + an2 ) ≥ 2an+1bn+1 (a1b1 + ... + anbn ) ȱ
an2+1bn2+1 = an2+1bn2+1 ȱ
ȱ ȱȱȱȱǰȱȱ DZȱ
104
Grundlegende Algorithmen mit Java
(a12 + a22 + ... + an2 + an2+1 )(b12 + b22 + ... + bn2 + bn2+1 ) ≥ (a1b1 + a2b2 + ... + an bn + an+1bn+1 ) 2 ǰȱ
ȱ
ȱȱȱǻƸŗǼǯȱ
§đȱȱ£ȱȱ§ȱ ȱǰȱȱȱȱǻǼȱûȱȱ
ûȱȱȱ≥ȱŗȱ ȱǯȱ÷ȱ
ȱ
Aufgaben
ŗǯ
ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ ȱ
ȱȱȱǰȱȱȱȱȱûDZȱ
ȱȱȱȱ
n
Ǽȱ
k =1
n
Ǽȱ
k4
¦ (2k − 1)(2k + 1) =
k =1
ȱ
Řǯ
n(n + 1)
k
¦ (2k − 1)(2k + 1)(2k + 3) = 2(2n + 1)(2n + 3) ȱûȱȱȱ≥ȱŗǯȱ
n(n + 1)(n 2 + n + 1)
ȱûȱȱȱ≥ȱŗǯȱ
6(2n + 1)
ȱȱȱȱȱûȱȱȱûȱȱ ȱ
ȱDZȱȱ
n
Ǽȱ S n = 1 ⋅1!+2 ⋅ 2!+... + n ⋅ n!=
¦ k ⋅ k! ȱûȱȱȱ≥ȱŗǯȱ
k =1
n
1 ·
1 ·
§ 1·
§
§
Ǽȱ Pn = ¨1 − ¸ ⋅ ... ⋅ ¨1 − 2 ¸ =
¨1 − 2 ¸ ȱûȱȱȱ≥ȱŘǯȱ
© 4¹
© n ¹ k =2 © k ¹
∏
řǯȱȱ ȱ¡ȱȱȱȱȱ¡ȱ≠ȱ±ȱŗǯȱ ȱȱûȱȱ∈ȱWDZȱ
ȱ
1
2
2n
1
2 n +1
ǯȱ
+
+ ... +
=
+
n
n +1
2
x −1 1− x2
1+ x 1+ x
1+ x2
ȱ
Śǯȱȱ ȱǰȱȱûȱȱûȱȱȱ≥ȱŗȱȱȱżz[DZȱ
ȱ
Ǽȱ cos α ⋅ cos 2α ⋅ ... ⋅ cos 2 n α =
sin 2 n +1α
ȱ
2 n +1 sin α
n +1
α
sin
nα
2
ǯȱȱ
sin
Ǽȱ sin α + sin 2α + ... + sin nα =
α
2
sin
2
5
Rekursion
105
śǯȱȱ ȱǯȱ ȱǰȱȱûȱȱȱ¡ȱȱ¡ȱǁȱȬŗȱȱȱ
∈ȱWȱDZȱ 1 + nx ≤ (1 + x) n ǯȱȱ
Ŝǯȱȱ ȱǰȱȱûȱȱûȱȱȱ≥ȱŗȱȱȱDZȱȱ
Ǽȱ 11n + 2 + 12 2 n +1 ȱȱȱŗřřȱDzȱȱ
Ǽȱ 4 n + 15n − 1 ȱȱȱşȱDzȱȱ
Ǽȱ 3 ⋅ 52 n +1 + 23n +1 ȱȱȱŗŝȱDzȱȱ
Ǽȱ 27 n + 3 + 32 n +1 ⋅ 54 n +1 ȱȱȱȱŘřǯȱ
ŝǯȱ ȱȬȱȱ ȱȱûȱȱȱ≥ȱŘȱDZȱǻŖǼȱƽȱŖǰȱǻŗǼȱƽȱŗǰȱǻǼȱƽȱ
ǻȬŗǼȱƸȱǻȬŘǼǯȱȱDZȱ
Ǽȱ F ( n + m) = F ( m + 1) ⋅ F (n) + F (m) ⋅ F ( n − 1) ȱûȱȱǰȱȱzWŮ0.
Ǽȱ F (n ⋅ k ) ȱȱȱȱ F (n) ȱûȱ ǰȱ zWŮ0.
Ǽȱ ûȱ ȱ ǰȱ z WŮ0ȱ DZȱ F ( kn − 1) ≡ F k ( n − 1) ( mod F 2 (n)) ȱ ȱ
F (kn − 2) ≡ (−1) k +1 F k (n − 2) (mod F 2 (n)) ǯȱ
Ǽȱ F (n ⋅ F (n)) ȱȱȱ F 2 ( n) ȱûȱȱȱzWŮ0.
Ǽȱ F (n ⋅ F m (n)) ist ûȱȱȱzWȱȱzWŮ0ȱ F m+1 ( n) ȱǯ
Rekursion: Grundlagen
ȱ ȱ ȱ ǻȱ ȱ ȱ
ȱ ƽȱ £ûǼȱ ȱ ǰȱ ȱ ȱ
Ǯȱ £ȱ ȱ ȱ ȃȱ ȱ ǯȱ
ȱ ȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ
§ȱ ȱ ûȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ Ȭ
ȱȱȱȱȱȬ
£ȱ ȱ ȱ £ȱ ǰȱ £ǯȱ ǯȱ ȱ §ȱ
ȱ ȱ ȱ ǯȱ ȱ Ȭ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ãȱ ǰȱ
ȱȱȱȱ ȱȱ
ǯȱȱȱȱȱǮûȱȱ ȃȱ§ȱȱȱȱȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǻûȱȱȱ£ȱȱȱȱǼȱȱȱǻȱ Ȭ
ȱȱ ȬǼǯȱ
ȱ
ȱȱȱȱ£ȱ ǰȱȱȱȱ£ȱǰȱ ȱȱ
ȱûȱȱȱȱȱǰȱȱȱȱȱȬ
106
Grundlegende Algorithmen mit Java
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǻ ȱ ûȱ ȱ ǰȱ ȱ
ȱȱǷǼǰȱǯǯȱ ȱȱȱǰȱȱûȱǰȱȱȱ
ȱȱȱȱ ǯȱȱȱȱ ȱȱȱȱ
ȱǯȱȱ
ȱ
ȱȱȱȱȱǰȱȱȱ ȱȱȱ ȱ
£ȱȱȱ§ȱȱȱ ãđȱȱ ȱ£Ȭ
ȱDZȱ
• ȱDZȱȱȱȱȱȱãȱãȱȱ Ȭ
ȱ ȱ ǰȱ ȱ £ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ãđȱ
ȱ
ȱ ǯȱ DZȱ §ǰȱ Ȭ
ǰȱȱȱȱȱȱȱ¢ǯȱ
• £ ȱȱǻǮȱȃǼDZȱȱȱȱȱȱãȱ
ȱ£ ȱȱȱ ȱȱǯȱ ȱȱȱûȱ ȱ
ȱȱǰȱȱ ȱȱȱȱȱȱǰȱ
ȱȱ ûȱȱ£ȱ ȱȱǻDZȱȬǰȱ
£Ǽǯȱ ȱ ãȱ ȱ ȱ ȱ ȱ ¢ȱ Ȭ
ȱ£ȱãǯȱ
• ȱȱǻǮȱȃǼDZȱȱȱûȱȱȬ
ȱȱȱȱ ȱȱȱȱǯȱȱȱ
ȱȱȱǻDZȱǰȱȬǼȱ
• ȱ ǻȱ Ǽȱ DZȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱ§ȱǻDZȱǻřƸŗǼȬȱȱ£Ȭ
Ǽǯȱ
ȱ
ȱȱ¢ȱãȱȱȱȱDZȱ
• ȱDZȱȱȱȱȱȱȱȱ
• ȱDZȱȱ£ ȱǰȱȱȱǯȱȱ
Problem 1. Quersumme und Spiegelung einer natürlichen Zahl
ȱȱȱǰȱȱȱȱȱȱȱûȬ
ȱȱȱǻǁŖǼȱǯȱȱȱȱǰȱȱȱȱȱȱ
ȱǯȱDZȱ
ȱ
Tastatur
Bildschirm
n= 34690213776
sumDigits(n)= 48
reverse(n)= 67731209643
ȱ
5
Rekursion
107
Problemanalyse und Entwurf der Lösung
ȱȱȱȱȱǻǼǰȱǻǼǰȱ ǻǼȱȱǻǼǰȱȱ
ȱȱ£ȱãǯȱȱȱȱ§ȱȱȱ §ȱûȱȱȱȱ
ǯȱȱûȱȱȱȱȱ ȱDZȱ
Ȭȱ ȱ ȱ ȱ £ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ £ǯȱ ȱ £ȱ ȱȱȱ
ȱȱȱȱȱȱȱŗȱǻǻȱȱŗŖǼȘ ǻŗŖǰǻǼȬŗǼǼǰȱȱ
Ȭȱȱȱȱȱȱȱȱȱ£ȱȱǻȱȱŗŖǼDZȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻǻȱȱŗŖǼȘ ǻŗŖǰǻǼȬŗǼƸǻȱȱŗŖǼǼǯȱ
Programm
import java.util.*;
public class P1DigitsSumAndReverse {
ȱȱȱûȱȱȱ
ȱȱȱȱ£ȱȱǻȱȱ
ŗŖǼȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǻ ŗŖǼǯ
private static long sumDigits(long number) {
return number==0
? number
: number%10+sumDigits(number/10);
}
private static long noDigits(long number) {
return number==0
ȱ£ȱȱȱȱûȬ
? number
: 1+noDigits(number/10); ȱ ȱ ȱ ŗȱ ȱ ȱ £ȱ ȱ
ȱȱ ȱ ȱ ȱ £ȱ Ȭ
}
ȱǻȱ ŗŖǼǯȱ
private static long pow(long base, long exp) {
return exp==0
­°1, wenn n = 0
?
bn = ®
1 : base *pow(base, exp-1);
°̄b ⋅ b n −1 , wenn n > 0
}
private static long reverse(long number){
return number==0
? 0 :
((number%10)*pow(10,noDigits(number)-1)+reverse(number/10));
};
public static void main(String[] args) {
System.out.print("n= ");
108
Grundlegende Algorithmen mit Java
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
System.out.print("sumDigits(n)= ");
System.out.println(sumDigits(n) );
System.out.print("reverse(n)= ");
System.out.println(reverse(n));
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱûȱȱȱȱȱȱȱȱȱȱǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǻǼǰȱǻǼǰȱ ǻǼȱȱǻǼǯȱȱ
ȱȱȱȱ ǻǼȱȱȱ£DZȱ
ȏ ȱ ȱǻǰȱǼȱȱȱ
ȱȱŗǯȱ e = e0 + e1 ⋅ 2 + e2 ⋅ 22 + ... + er ⋅ 2 r ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱŖǰȱŗǰȱdzǰȱȱzȱǿŖǰȱŗȀȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱǻȱȱȱȱ§¢Ǽȱ
ȱȱŘǯȱ e = e0 + 2 ⋅ (e1 + 2 ⋅ (e2 + 2 ⋅ (... + 2(er −1 + 2 ⋅ er ))...)) ȱ
e
e
ȱȱřǯȱ b e = (...(((b r ) 2 ⋅ b r −1 ) 2 ⋅ b r −2 ) 2 ⋅ b r −3 ) ⋅ ...) 2 ⋅ b 0 ȱȱ
e
e
e
ȱȱŚǯȱ ȱȱȱȱȱȱ ȱ
ȱ£ȱȱȱȱŗȱ£ ǯȱǰȱȱǰȱ
ei ȱŖȱȱŗȱǯȱ
ȏȱ ȱ ȱǻǰȱǼȱȱȱȱȱ
ȱ
ȱ
ȱ
Śǯ
śǯ
ȱ ¡§ȱȱȱȱǻȱǼǰȱ ȱȱȱ¡ȱǯȱ
ȱȱȱȱȱǰȱȱȱȱǷȱƽȱŗȉŘȉdzȉȱȱ
ǻǼȱƽȱŗȱƸȱŘȱƸȱdzȱƸȱȱǯȱ
ȱȱȱȱȱȱȱǰȱȱȱȱǻǰȱ
ǼȱƽȱȱƸȱǻƸŗǼȱƸȱdzȱƸȱȱȱǻ ȱǁȱǰȱȱȱȱŖȱǼǯȱ
Problem 2. Die Zahl 4
ȱȱȱȱȱûȱȱȱ Ȭ
ǰȱûȱȱȱ £ȱȱûȱȱȱȬ
ǯȱȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱûȱȱȱȱȱ
£ȱ ǯȱ ȱ ȱ ȱ ȱ ûȱ
5
Rekursion
109
DZȱ
Ǽ ȱûȱȱȱȱȱŚȱ£Dzȱ
Ǽ ȱûȱȱȱȱȱŖȱ£Dzȱ
Ǽ ȱȱȱȱŘȱǻ ȱȱȱȱǼǯȱ
ȱȱ§ȱȱ؜،ǰȱ ȱȱȱȱȱŚȱȱȱȱ
£ȱ ûǯȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ
Śǯȱ£ǰȱ ȱȱ ȱȱȱȱŚȱȱ ȱȱȱȬ
ȱǰȱȱȱȱȱȱȱŚǯǯȱDZȱ
ȱ
nr4.in
nr4.out
2524
4->2->1->10->5->50->504->252->2524
564
4->44->22->224->112->56->564
12
4->2->24->12
3
4->2->24->12->6->3
ǻȱȱȱ ȱ£ȱ ǰȱDZȱǯ ǯȱǼȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱȱȱ£ȱȱȱȱǰȱȱ ȱȱȱȱȱȱ
£ȱŚȱǯȱ£ȱ ȱ ȱȱȱȱȱȱDZȱ
ȱ
′ǼȱȱȱȱȱŚǰȱ ȱȱȱȱDzȱ
′ǼȱȱȱȱȱŖǰȱ ȱȱȱȱDzȱ
′Ǽȱȱ£ȱȱȱȱŘǯȱ
ȱ
ǰȱȱȱȱȱûȱȱȱȱȱȱ£ȱȱȱŚȱ
ȱǯȱȱãȱȱȱȱ£ȱȱ£ȱȱûȱȱ Ȭ
ȱȱ ȱûǯȱȱûȱȱǰȱ ȱȱ£ǰȱȱȱȱȬ
ȱȱ ≥ȱŚȱȱȱȱȱȱǯȱȱȱȱǰȱȱȱ
ȱȱȱȱȱŘȱȱȱȱȱǯȱȱ£ȱȱ
ȱȱȱȱûȱȱ DZȱȱ
ȱ
Ǽ
ŗŖȱ→ȱDzȱȱ
Ǽ
ŗŖȱƸȱŘȱ→ȱŘŖȱƸȱŚȱ→ȱŘDzȱ
Ǽ
ŗŖȱƸȱŚȱ→ȱȱ→ȱŘDzȱ
Ǽ
ŗŖȱƸȱŜȱ→ȱŘŖȱƸȱŗŖȱƸȱŘȱ→ȱŚŖȱƸȱŘŖȱƸȱŚȱ→ȱŚȱƸȱŘDzȱ
Ǽ
ŗŖȱƸȱŞȱ→ȱŘŖȱƸȱŗŖȱƸȱŜȱ→ȱŚŖȱƸȱřŖȱƸȱŘȱ→ȱŞŖȱƸȱŜŖȱƸȱŚȱ→ȱŞȱƸȱŜǯȱ÷ȱȱ
ȱ
ûȱȱ ȱȱȱȱǻǼǯȱȱ
ȱ
110
Grundlegende Algorithmen mit Java
Programm
import java.io.*;
import java.util.*;
public class P02Number4 {
private static final String FileInputName = "nr4.in";
private static final String FileOutputName = "nr4.out";
private static
StringBuilder numberFour(int number, StringBuilder out) {
if (number != 4) {
switch (number % 10) {
case 0:
case 4:
numberFour(number / 10, out);
break;
default:
numberFour(number * 2, out);
}
out.append("->");
}
out.append(number);
return out;
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNextInt()) {
int number = sc.nextInt();
out.println(numberFour(number, new StringBuilder()));
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
5
Rekursion
111
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱûȱȱȱȱŚǯȱȱǯȱ
ȱȱȱȱȱȱûǯȱ
Problem 3. Rest großer Potenzen
ȱȱȱȱ R = B P mod M ǰȱ ȱǰȱȱȱȱûȱȱǰȱȱ
Ŗȱ≤ȱǰȱȱ≤ȱŘŖŖǯŖŖŖǯŖŖŖȱȱŖȱ ≤ȱȱ≤ȱśŖǯŖŖŖǯȱDZȱ ȱȱȱǯȱȱȱ
ȱ §ȱ ȱ ǰȱ ȱ ȱ ȱ ǯȱ DZȱ ȱ ȱ ȱ
ǯȱȱȱûȱȱȱǻǰȱǰȱǼȱȱȱ R = B mod M ǯȱȱDZȱ
p
bigmod.in
3 18132 17
17 1765 3
2374859 3029382 36123
bigmod.out
13
2
13195
ǻDZȦȦǯǯȦȦřȦřŝŚǯǼȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱȱ§ȱ£ȱǰȱȱ ȱȱ ȱ ȱȱȱ
ȱǯǯȱȱ ȱȱȱ ãȱȱȱ
ȱ ȱ £ȱ ǯȱ ȱ ȱ ǻǼȱ ȱ £ ȱ
ȬȱȱȱȮŗǰȱŖȱȱŗȱ£ûǯȱȱȱȱȱȱ
ȱȱȱȱ ¢ȱDZȱȱ
ȱ
ǻ ȱǼȱȱȱ
ȱ ȱ ãđȱ ȱ ȱ ȱ
ǻǼȱȱǻǼȱ£ûȱ
ǻ ȱ¡ǰȱ ȱǼȱȱȱ ȱ ȱ Ȭ £ȱ £ûǰȱ ȱ
ȱ this exp mod m ȱ
ǻȱ¢Ǽȱȱȱ
ȱ ȱ £ûǰȱ
ȱ Ȭ ȱ
ȱȱȱȱǰȱ ȱȱȱ
££ȱȱȱ
ȱ
ȱ£ȱȱȱ ȱ ȱȱǯȱȱȱȱȱ§ȱȱtȱȱ
ȱȱ ǻǼȱȱȱȱȱ ǯȱ
£ǯȱûȱȱǰȱǰȱȱ∈ȱW{0},ȱȱǻȉǼȱȱƽȱǻǻȱȱǼȉǻȱȱǼǼȱȱǯȱȱ
ȱ ŗǯȱ ¡ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱ£ ȱŖȱȱȬŗǰȱûȱȱȱ¡ȱȬȱ¡ȱȱȱȱȱȱǯȱȱȱ
ȱ£ȱ£ǰȱȱ a ⋅ b − (a%c) ⋅ (b%c) ȱȱȱǯȱȱȱȱ
ȱ
µȱȮȱǻȱȱǼµǻȱȱǼȱƽȱµȱȮȱµȱǻȱȱǼȱƸȱµȱǻȱȱǼȱȮȱǻȱȱǼµǻȱȱǼȱƽȱȱ
112
Grundlegende Algorithmen mit Java
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱƽȱȱµȱǻȮȱǻȱȱǼǼȱƸȱǻȱȱǼȱµȱǻȮǻȱȱȱǼǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ȱ
ȱȱȱȱȱȱȱ. ÷
ȱŘǯȱ §đȱȱ′ȱ£ȱȱ ȱ£DZȱ
∃R ∈ {0,..., c − 1} so dass a ⋅ b = Q ⋅ c + R →
R = (a ⋅ b)%c = a ⋅ b − Q ⋅ c
∃R1 ∈ {0,..., c − 1} s.d. a = Q1 ⋅ c + R1 , R1 = a mod c
∃R2 ∈ {0,..., c − 1} s.d. b = Q2 ⋅ c + R2 , R2 = b mod c
ǻŗǼȱ
(2)
a ⋅ b = Q3 ⋅ c + R1 ⋅ R2
(a ⋅ b) mod c = ( R1 ⋅ R2 ) mod c = ( a mod c ⋅ b mod c) mod c . ÷
ȱ
ȱ ȱȱȱȱǻǼȱǰȱȱȱȱ£ȱDZȱ
ȱ
­a ) 1, wenn P = 0
°b) 0, wenn nicht a) gilt und B = 0
°
°c) B%M , wenn nicht a) oder b) gilt und ( B = 0 oder P = 1)
°°
bigMod ( B, P, M ) = ®d) (BigMod(B, P/ 2,M)2 )%M , wenn nicht a), b) oder c) ȱ
° gilt und P gerade ist
°
°e) (BigMod(B, P-1, M) ⋅ (B % M))%M , wenn nicht
°
¯° a), b), c) oder d) gilt und P ungerade ist
Programm
import java.io.*;
import java.util.*;
public class P03BigMod {
private static final String FileInputName = "bigmod.in";
private static final String FileOutputName = "bigmod.out";
private static long bigMod(long b, long p, long m) {
if (0 == p)
return 1;
if (0 == b)
return 0;
if (1 == b || 1 == p)
return b % m;
5
Rekursion
113
if (1 == m)
return 0;
if (0 == p % 2) {
long aux;
aux = bigMod(b, p / 2, m);
return (aux * aux) % m;
} else
return (bigMod(b, p - 1, m) * (b % m)) % m;
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNextLong()) {
long b = sc.nextLong();
long p = sc.nextLong();
long m = sc.nextLong();
out.println(bigMod(b, p, m));
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
śǯ
ȱȱȱȱȱûȱȱǯȱ
ȱ ȱ ȱ ȱ £ȱ ȱ ȱ DZȱ ȱ ȱ ȱ ƽȱ ȱ Ȯȱ ǻȱ
ȱǼǰȱǻǻȱȱǼȉǻȱȱǼǼȱȱȱƽȱǻǻȬǻȱȱǼǼµǻȬǻȱȱǼǼǼȱƽȱǯǯǯȱ
ȱȱȱȱȱ Ȭ ȱǻDZȦȦǯǯȦȦŜȦȦȦǼȱȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱ ǯȱ
ãȱȱȱȱȱȱ ȱ ȱȱȱȱ ǻǼǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǰȱ ȱ Ƿȱ ǻȱ
§Ǽȱûȱȱđȱȱȱ£ȱǯȱDZȱǷȱƽȱŗµŘµdzµǯȱȱ
114
Grundlegende Algorithmen mit Java
Ŝǯ
ȱȱȱûȱȱŗǰȱŘǰȱdzǰȱǰȱȱȱȱŘǯŖŖŖǯŖŖŖǰȱȱȱ
ȱȱǀśŖǯŖŖŖǯȱȱȱȱǰȱȱȱȱǻŗ⋅Ř⋅ǯǯǯ⋅Ǽȱ
ŝǯ
Şǯ
ȱ ȱ ǯȱ ȱ ȱ £ ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱǯǯ ȱȱȱȱȱ ǯȱ
ȱ ȱǰȱȱȱȱȱǯǰȱȱȱãǰȱ
ȱȱ £ȱ£ȱǯȱȱȱȱȱȱ Ȭ
Ȭ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱȱ ȱ ǯȱ
tan
π
4
= 1 ȱȱ π = 4 ⋅ arctan 1 ȱ
ȱ
ȱ
ȱȱȱ
ȱ
ȱȱǻřǼȱ
ȱ ȱ ȱ ¢ȱ ǻŗŜřŞȬŗŜŝśǼȱ ȱ ȱ ȱ £ȱ
ǻŗŜŚŜȬŗŝŗŜǼȱȱǯȱŗŜŝŖȱ§ȱȱȱȱȱ
ȱûȱȱDZȱ
arctan x = x −
x3 x 5 x 7
+
−
+ ..., ûȱȱ¡ȱz[ȱȱ¡≤ȱŗȱȱ
3
5
7
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻŚǼȱ
ȱȱȱȱȱ DZȱ
ȱ
arctan x =
ȱ
§ x 2 n +1 ·
¸, ȱûȱȱ¡ȱz[ȱȱ¡≤ȱŗȱ
(−1) n ¨¨
¸
n=0
© 2n + 1 ¹
∞
¦
ȱ
ȱ
ǻśǼȱ
ȱ
ȱ
ȱ
Gottfried Wilhelm Leibniz (1646-1716)
James Gregory (1638-1675)
ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
π = 4 ⋅ arctan 1 ȱǰȱȱ ȱȱ DZȱ
5
Rekursion
115
≅ȱπȱ
0 4
1 2.666666666666667
2 3.4666666666666668
3 2.8952380952380956
4 3.3396825396825403
5 2.9760461760461765
100000 3.1416026534897203
100001 3.1415826537897158
200000 3.1415976535647618
200001 3.1415876536397613
300000 3.1415959869120198
300001 3.1415893202786864
400000 3.1415951535834941
400001 3.1415901536022441
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻȱ
ȱȱǁȱ πǼǰȱ ȱȱȱȱȱ ȱȱ
ȱ ǻȱ ȱ ȱ ǀȱ πǼǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǯǯȱ ȱ £ȱ πȱ ȱ ŗŖŖȱ ȱ
¡ȱǯȱȱ
ȱȱȱǯȱ ȱ ȱŗŝŖŜȱȱȱȱȬ
ȱ ȱ ȱ ǻŗŜŞŖȬŗŝśŗǼȱ ȱ ȱ ǰȱ ȱ πȱ ȱ
ǯȱȱȱȱȱȱπȱȱŗŖŖȱȱȱDZȱ
ȱ
şǯ
π
1
1
= 4 arctan − arctan
4
5
239
(6)
ȱȱȱǰȱȱπȱȱŗŖŖŖȱȱȱȱǻŜǼǰȱǻŚǼȱȱȱ
ȱȱǯȱ
Problem 4. Die Torte (lineare Rekursion)
ȱ ȱ ¢ȱ ȱ ȱ ûȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ đȱ ȱ ûǯȱ ȱ
1
ȱ ȱ ãȱ ȱ ŝȱ ûȱ ǰȱ ȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ
6
2
ȱ¡ȱȱȱȱǵȱǻȱȱ
7
ȱȱȱȱȱȱ¡ȱ£ǰȱ
ȱȱȱ ȱȱǵǼȱDZȱ ȱȱ
5
3
ȱ ǯȱ ȱ £ ȱ ȱ £ȱ ȱ Ȭ
4
ȱȱǻŖȱ ≤ȱȱ ≤ȱŘǯŖŖŖǼǯȱDZȱȱȱ
ȱ ǯȱ ȱ ¡ȱ £ȱ ȱ ûǰȱ
ȱȱ
ȱȱȱȱȱȱǯȱDZȱ
116
Grundlegende Algorithmen mit Java
torte.in
0
1
2
9
10
2000
678
ȱ
torte.out
0 Schnitte ->
1 Stuecke!
1 Schnitte ->
2 Stuecke!
2 Schnitte ->
4 Stuecke!
9 Schnitte ->
46 Stuecke!
10 Schnitte ->
56 Stuecke!
2000 Schnitte -> 2001001 Stuecke!
678 Schnitte -> 230182 Stuecke!
Problemanalyse und Entwurf der Lösung
ȱȱ¡ȱ£ȱȱ ȱûȱȬŗȱȱȱ ȱǻȬŗǼȱǰȱ
ȱȱȱȱȱ ȱȱ ȱ£DZȱ
ȱ
ǻŖǼȱȱƽȱŗȱȱȱǻȱȱ→ȱȱȱȱûDZȱȱ£ȱǼȱ
ǻǼȱƽȱȱƸȱǻȬŗǼȱǰȱûȱȱǁŖȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŗǼȱ
ȱ
ȱȱǻŗǼȱȱȱȱǰȱȱ ȱȱȱȱȱ
ǻǼǯȱȱ
ȱ
Programm 4.1.
import java.io.*;
import java.util.*;
public class P4Tart1 {
private static final String FileInputName = "torte.in";
private static final String FileOutputName = "torte.out";
private static int S(int n){
if(n<1)return 1;
else
return n + S(n-1);
}
public static void main(String args[]) throws IOException {
Scanner sc = null;
PrintStream out= null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName ));
while(sc.hasNextInt()) {
int n = sc.nextInt();
out.printf(
"%4d Schnitte -> %7d Stuecke!%n", n, S(n));
}
5
Rekursion
117
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}ȱ
ȱ
ȱǰȱȱȱȱûȱãđȱȱȱȱǻǼȱȱȱǰȱ
ȱȱȱȱ£ȱȱȱǯȱȱȱǻŗǼȱȱǰȱȱȱ
n ⋅ (n + 1)
ǯȱȱ ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŘǼȱ
ǻǼȱƽȱȱƸȱǻȬŗǼȱƽȱȱƸȱǻȬŗǼȱƸȱǻȬŘǼȱƽȱdzȱƽȱ 1 +
2
ȱ
Programm 4.2.
import java.io.*;
import java.util.*;
public class P4Tart2 {
private static final String FileInputName = "torte.in";
private static final String FileOutputName = "torte.out";
public static void main(String args[]) throws IOException {
Scanner sc = null;
PrintStream out= null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName ));
while(sc.hasNextInt()) {
int n = sc.nextInt();
out.printf(
"%4d Schnitte -> %7d Stuecke!%n", n,1 + n*(n+1)/2);
}
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}ȱ
118
Grundlegende Algorithmen mit Java
Aufgabe
ȱȱǯȱȱȱȱ¡ȱ£ȱȱ ȱǰȱȱȱȬ
n(n + 1)
£ȱȱȱȱǯȱȱȱȱǯȱȱȱȱȱ 1 +
ȱȬ
2
ǯȱDZȱ
ȱ
reg.in
reg.out
56
10
2001001
2000
230182 ȱ
678ȱ
ȱ
Problem 5. Die Ackermannfunktion
(Verschachtelte Rekursion, "compound recursion")
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ
ǯȱûȱȱȱȱŗşŘŜȱȱȱǰȱȱ¡Ȭ
ȱ ȱ §ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
£ȱȱȱ ǯȱȱȱȱȱ£ȱȱȬ
ȱûȱȱȱǯȱ
ȱ
Die ȱû ǰȱ ∈ W ȱȱDZȱ
­m + 1, wenn n = 0
°
Ack (n, m) = ® Ack (n-1, 1), wenn m = 0
° Ack (n-1, Ack (n, m-1)), wenn m ≠ 0 und n ≠ 0
¯
ȱ ȱ §ȱ ȱ DZȱ ǻřǰȱ ŚǼƽŗŘśǰȱ ȱ ǻŚǰȱ ŘǼȱ £ȱ Ȭ
ȱŗşŝŘşȱ£Ƿȱȱȱȱǰȱȱȱȱ
ûȱȱǻǰȱǼȱǯȱDZȱ
ack.in
0 2
2 0
3 4
3 5
3 2
ȱ
ack.out
Ack(0, 2)= 3
Ack(2, 0)= 3
Ack(3, 4)= 125
Ack(3, 5)= 253
Ack(3, 2)= 29
5
Rekursion
119
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱ
ȱ
ȱ ȱ ȱ ȱ ǻǼȱ
Programm
import java.io.*;
import java.util.*;
public class P5Ack {
private static final String FileInputName = "ack.in";
private static final String FileOutputName = "ack.out";
private static long ack(long n, long m){
if(0==n) return m+1;
else if(0==m) return ack(n-1, 1);
else return ack(n - 1, ack(n, m - 1));
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out= null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName ));
while(sc.hasNextLong()) {
long n = sc.nextLong();
long m = sc.nextLong();
out.print("Ack(");
out.print(n);
ȱ£DZȱ
out.print(", ");
out.println("Ack(" + n + ", " + m
+ ")= " + ack(n, m));
out.print(m);
out.print(")= ");
out.println(ack(n, m));
}
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}ȱ
120
Grundlegende Algorithmen mit Java
Aufgabe
Ȭǯȱ ȱȱȱǰȱȱȱûȱȱȱ£ȱȱȱȱ¡ȱȱȱȬŗŖŖŖȱȱ≤ȱ
¡ȱ≤ȱŗŖŖŖȱȱȱȱ ȱȱȱǮȬȃȬȱȱǻ¡ǼȱȱDZȱ
ȱ
­ x − 1, wenn x ≥ 12
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
¯ f ( f ( x + 2)), wenn x < 12
ȱDZȱ]Ř] f ( x) = ®
DZȱ
mp.in
12
34
56
-123
98
678
-234ȱ
mp.out
Manna-Pnueli(12)= 11
Manna-Pnueli(34)= 33
Manna-Pnueli(56)= 55
Manna-Pnueli(-123)= 11
Manna-Pnueli(98)= 97
Manna-Pnueli(678)= 677
Manna-Pnueli(-234)= 11
Problem 6. Rekursive Zahlenumwandlung (Dezimalsystem in
System mit Basis p)
ȱȱȱȱǰȱȱȱȱȱȱǻŖȱ≤ȱȱ≤ȱşǯŖŖŖǯŖŖŖǼȱȱ
ȱ£¢ȱȱȱ¢ȱȱȱȱǻŘ≤≤ŗŖǼȱ ǯȱDZȱ
ȱ
baseP.in
baseP.out
324123534 2
324539 9
654789045 6
675432 4
9000000 8
3 2
8 6
324123534 zur Basis 2 = 10011010100011011101110001110
324539 zur Basis 9 = 544158
654789045 zur Basis 6 = 144550222433
675432 zur Basis 4 = 2210321220
9000000 zur Basis 8 = 42252100
3 zur Basis 2 = 11
8 zur Basis 6 = 12
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱȱȱȱȱǯȱûȱȱȱ¢ȱȱǻȬ
Ȭ ȱ ûȱ Ǽǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ££ǯȱ Ȭ
ȱ¡ȱ£ȱȱȱ¢ȱǻ¢ǰȱǰȱǰȱǰȱǰȱǼȱȱ
£ȱȱ¢ȱȱȱǯȱȱȬ ȱȱȱȱȱ
ȱ
static String toString(long i, int radix)
ȱ
ȱ ȱ ȱ £ûǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ ȱ
ȱ££ȱ ǰȱǯȱ ȱȱȱȱȱȱ
5
Rekursion
121
ȱȱ
Long.toString(n, p)ȱ
ȱ
ȱȱȱȱȱȱȱǯȱȱȱȱȱ£ȱǰȱȬ
ȱȱtǰȱ ȱ£ȱ ǰȱ ȱȱȱȱȱ ȱ
ȱȱȱȱǯȱ
ȱ
ȱȱȱȱȬŗdzŗŖȱȱ¢ȱȱȱȱȱǰȱȱDZȱ
ȱ
N = ak ak −1...a1a0 = ak p k + ak −1 p k −1 + ... + a1 p + a0 , ak , ak −1,..., a0 ∈{0,1,..., p − 1} ȱ
ȱ
ȱȱ N = p(ak p k −1 + ak −1 p k − 2 + ... + a1 ) + a0 ǯȱȱ
ȱ
ȱȱȱȱDZȱ
ȱ
ȱ
ȏŗŖǻǰȱǼȱ
ȱ
ȱȱȱ ȱǻǁŖǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱ ȏŗŖǻȱȱǰȱǼȱȱ
ȱ
ȱȱȱȱȱȱȱǻȱƖȱǼȱ
ȱ
ȱȱȱȱȏ ȱ
ȱ
ȏȱ ȏŗŖȱǻǰȱǼȱ
ȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P6BaseP {
private static final String FileInputName = "baseP.in";
private static final String FileOutputName = "baseP.out";
private static void transfBase10ToP(long n,
int p, PrintStream out) {
if(n>0){
transfBase10ToP(n/p, p, out);
out.print(n%p) ;
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out= null;
122
Grundlegende Algorithmen mit Java
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName ));
while(sc.hasNextLong()) {
long n = sc.nextLong();
int p = sc.nextInt();
out.printf("%10d zur Basis %d = ", n, p);
transfBase10ToP(n, p, out);
out.println();
}
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}ȱ
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱȱȱȬȱǰȱȱȱȱãǯȱ
ȱȱȱȱ Ȭȱûȱȱȱȱȱȱ ȱǯȱ
ȱȱȱǰȱȱȱȱȱ£ǯȱ
ȱ ȱ ȱ §ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǻǼȱȱȱȬ ȱȱãǯȱ
ȱȱȱȱǻȱȱȱǼȱûȱȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ǻǰȱ Ǽǰȱ ȱ ȱ
ȱȱȱȱȱȱ¢ȱȱȱȱȱȱȱ££ȱ
ǯȱDZȱ
ȱ
baseP10.in
42252100 8
11 2
12 6 ȱ
baseP10.out
9000000
3
8ȱ
ȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ
ȱȱȱǻǼȱȱȱ ȱǯȱ
5
Rekursion
123
Problem 7. Summe zweier Wurzeln (verzweigte Rekursion)
− Sx + P = 0 ȱȱǰȱȱ ∈ȱ[ȱǯȱ¡ŗȱȱ¡ŘȱȱȱȬ
n
n
£ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Tn = x1 + x2 für n ∈ Wȱ ǯȱ ȱ
ȱȱȱ ȱ x
2
ȱǰȱȱȱ£ȱ¡ŗȱȱ¡Řȱ£ȱǯȱȱȱȱǰȱȱȱȬ
śŖŖȱ≤ȱȱǰȱȱ≤ȱśŖŖȱȱȱûȱȱȱǻŖȱ≤ȱȱ≤ȱŘŖǼȱȱȱȱǰȱȱȱ
ȱǯȱDZȱ
ȱ
equation.in
equation.out
5 6.54 3.22
7799.79
0 3 4
2
1 3.45 6.78
3.45
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ¡ŗȱ ȱ ¡Řȱ ȱ £ȱ ȱ ȱ ǰȱ x 2 − Sx + P = ( x − x1 )( x − x2 ) ǯȱ
ȱȱ x1 + x2 = S ȱ x1 ⋅ x2 = P ȱǻȱȬǼǯȱȱȱûȱȱȱDZȱ
ȱ
­2, wenn n = 0
°
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱ ȱ
Tn = ® x1 + x2 , wenn n = 1
°ST − PT , wenn n > 1
n−2
¯ n−1
ȱ
ȱ
ǻŗǼȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ¡ȱ ãȬ
ǰȱȱ¢ȱȱ£ǯȱȱ¡ȱȱȱ ȱśȱȱ
ȱ §ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ƸƸǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ¢ȱ ȱ ȱ ǰȱ ȱ ȬȦ ȱ ȱ ȱ
ǯǯȱȱǯǯȱȱ§ȱȱǻȱ§£ǼȱȬ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ Ȭ
ȱȱȬȱ£ȱȱȱȱǻǼȱȱ ǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P7Equation {
private static final String FileInputName = "equation.in";
private static final String FileOutputName = "equation.out";
private static double sum(int n, double s, double p){
if(0==n) return 2;
if(1==n) return s;
124
Grundlegende Algorithmen mit Java
return s*sum(n-1, s, p)-p*sum(n-2, s, p);
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out= null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(
new File(FileInputName)).useLocale(Locale.ENGLISH);
Formatter formatter =
new Formatter(out, Locale.ENGLISH);
while(sc.hasNextInt()) {
int n = sc.nextInt();
double s = sc.nextDouble();
double p = sc.nextDouble();
formatter.format("%.6g%n", sum(n, s, p));
}
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}ȱ
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
ȱȱȱȱǻŗǼȱȱȱȱ§ȱ ǯȱ
ȱȱȱȱȱ Ȯ ȱǻDZȦȦǯǯȦȦŜȦȦǼȱȱȬ
ȱȱȱȱȱȱ ȱȱǯȱ
ǯȱ ȱ ȱ ûȱ ȱ
ȱ Ȭȱ
ȱ
x k − S1 x k −1 + ... + (−1) k S k = 0 ȱ ȱ ȱ £ȱ ¡ŗǰȱ ¡Řǰȱ dzǰȱ ¡ȱ ȱ ȱ
Tn = x1n + x2n + ... + xkn ǯȱȱ
ȱ
DZȱȱȱȱȱȱ
Tn = S1Tn−1 − S 2Tn−2 + ... + (−1) k −1 ⋅ S k ⋅ Tn−k ǯȱ
ȱ
5
Rekursion
125
Problem 8. Collatz-Funktion (nicht-monotone Rekursion)
ȱ£Ȭȱȱȱ ȱDZȱ
ȱ
­1, wenn n = 1
°n
°
ȱ
f (n) = ® , wenn n gerade
°2
°¯3 ⋅ n + 1, wenn n ungerade
ȱȱȱǰȱȱȱȱŗȱǮȃǯȱȱȱ ȱûȱƽŗŘȱ
ȱȱ£DZȱŗŘǰȱŜǰȱřǰȱŗŖǰȱśǰȱŗŜǰȱŞǰȱŚǰȱŘǰȱŗȱȱȱȱȱȱ§ȱşǰȱ ȱȱȱ
şȱȱȱȱǯȱȱȱȱȱǰȱȱȱ£ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǯȱ Ȭ
DZȱ
ȱ
collatzSeq.in
collatzSeq.out
1 <0>
1
12
12 6 3 10 5 16 8 4 2 1 <9>
67
1003
67 202 101 304 152 76 38 19 58 29 88 44 22 11
234
34 17 52 26 13 40 20 10 5 16 8 4 2 1 <27>
1003 3010 1505 4516 2258 1129 3388 1694 847
2542 1271 3814 1907 5722 2861 8584 4292 2146
1073 3220 1610 805 2416 1208 604 302 151 454
227 682 341 1024 512 256 128 64 32 16 8 4 2 1
<41>
234 117 352 176 88 44 22 11 34 17 52 26 13 40
20 10 5 16 8 4 2 1 <21>
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱȱȱȱ£ǻǼȱǰȱȱȱȱȬ
ȱȱȱȱ£ȱȱȱ£§ǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P08CollatzSeq {
private static final String FileInputName = "collatzSeq.in";
126
Grundlegende Algorithmen mit Java
private static final String FileOutputName =
"collatzSeq.out";
private int step;
private PrintStream out;
public P08CollatzSeq(PrintStream outStream) {
this.step = 0;
this.out = outStream;
}
public void calculate(long n) {
this.out.print(n);
this.out.print(' ');
if (n != 1) {
this.step++;
this.calculate(n%2 == 0 ? n/2 : 3*n+1);
} else {
out.print("<" + this.step);
out.print('>');
out.println();
out.println();
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNextLong()) {
P08CollatzSeq col = new P08CollatzSeq(out);
col.calculate(sc.nextLong());
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
5
Rekursion
127
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱȱûȱȱǯȱ
ȱ £ȱ ȱ ȱ ȱ Ǯ ȃȬȱ ȱ ȱ ȱ ȱ ǮřƸŗȃȬ
ǯȱ ȱȱȱȱǰȱȱȱȱãȱȬȱȱȬ
ȱ£§ȱ ǯȱûȱƽŗŘȱȱȱ£ǯȱǯȱŝȱȬȱȱŘȱȬȱȬ
DzȱûȱƽŗŖŖřȱȱȱŘşȱȬȱȱŗŘȱȬȱǯȱȱ
ȱȱȱǰȱȱȱûȱȱȱȱȬ
ȱ ȱǰȱûȱȱȱãȱȱȱ£ȬȱȬ
¡ȱ ȱ ǻ£ǯȱ ǯȱ ȱ ȱ ȱ ȱ ǽŚśDzȱ ŚśşǾȱ ȱ ȱ řŘŝǰȱ ûȱ ȱ ŗŚřȱ
ȱãȱǼǯȱȱȱȱȱȱȱȱ ǰȱûȱȱȱ
£ȱȱȬȱ£ ǯȱȬȱ¡ȱ ǯȱ
Problem 9. Quadrate und Quadrätchen
ȱǰȱȱȱȱ£ȱȱ ȱǰȱȱȱ
ȱȱȱȱȱȱ§ȱǯȱȱǰȱȱ
ȱȱȱȱ§ȱŘƸŗȱȱ ãđȱȱǯȱûȱȱûȱȱȱȬ
ȱ ȱȱȱȱȱȱȱDZȱ
ǻǼ
ȱãđȱȱȱȱ ãđȱȱǻȱ§ȱȱŘƸŗǼȱȱȱȱ
ȱ £ȱ ȱ ãđȱ ŗŖŘŚȱ £ȱ ǻȱ £ȱ ȱ ȱ §ȱ
ŘŖŚşǼDzȱ
ǻǼ
ûȱȱ ãđȱȱȱȱDZȱŗȱǂȱȱǂȱśŗŘDzȱ
ǻǼ
ȱǰȱȱãđȱȱŗȱǰȱȱȱȱȱ ãđȱȱȱŘȱ
ȱȱȱȱȱ£Dzȱ
ǻǼ
ȱȱȱȱȱ£ȱȱȱ ȱǻŖǰȱŖǼȱȱȱȱ
ȱȱȱȱ ȱǻŘŖŚŞǰȱŘŖŚŞǼǯȱ
ûȱȱȱȱȱãȱ ȱȱȱȱȱȱȱȬ
ȱȱ £ǯȱȱȱ ȱȱ£ȱ ȱȱȱǰȱ ȱ
ȱȱǯȱȱȱȱǰȱȱȱȱȱȱȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ǯȱDZȱ ȱȱȱȱǯȱȱȱȱȱȱȱǰȱ¡Ŗȱ
ȱ ¢Ŗȱ ȱ ȱ ǯȱ DZȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ
ȱǯȱȱ£ȱȱȱǰȱȱȱȱȱȱǻ¡Ŗǰȱ
¢ŖǼȱǯȱDZȱ
ȱ
quadrate.in
quadrate.out
56 1012 1000
1
500 1000 1000
4
500 113 941
5
1100 512 512
5
ǻȱȱȱǰȱŗşşŘǼȱ
128
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱȱããȱ §ǰȱȱûȱȱȱ£ȱûǰȱȱȱȱ
ȱ ȱ ǯȱ ȱ ȱ £ǰȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱȱȱǻ¡Ŗǰȱ¢Ŗǰȱ¡ǰȱ¢ǰȱǼǰȱȱȱûȱǯȱȱȬ
ȱ£ȱȱȱǻ¡Ŗǰȱ¢ŖǼȱȱȱȱȱȱȱǻ¡ǰȱ¢Ǽȱȱ
ȱ ãđȱǯȱȱȱǻǼȱ£§ǰȱȱ ȱȱȱȱȱȱ
ǯȱȱ ȱȱûȱȱȱ£ȱȱȱ ãđȱȦŘȱǯȱȱ
ȱ
£ǯȱȱ ȱȱȱ£ȱȱȱȱȱȱȱȱ
ȱ £ǰȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ
£ ǰȱûȱȱȱȱȱȱȱȱûȱȱȱȱȱȱȱ
ǯȱ
ȱ
II
I
III
IV
ȱ
ȱ
ǯȱȱȱȱ§ȱȱȱȱǰȱȱȱ ǰȱȱ
k k k
ȱȱȱ£ȱȱȱȱ§ȱȱȱ§ȱ ǰȱ ǰȱ ǰȱ
2 4 8
k
dzǰȱ n ǰȱǯǯǯȱǯȱȱȱȱȱȱǰȱȱȱDZȱ
2
ȱ
k k
k
k
1 ·
§
+ 2 + 3 + ... + n = k ⋅ ¨1 − n ¸ ǯȱ
2 2
2
2
© 2 ¹
5
Rekursion
129
1 ·
§
ȱȱ k ⋅ ¨1 − n ¸ ûȱȱƽȱŖǰȱŗǰȱŘǰȱǯǯǯȱȱȱȱȱȱǯȱȱǰȱ
© 2 ¹
ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
ǯȱȱȱ¢ȱȱȱûȱȱȱȱȱȱ
ȱȱȱ£ãȱȱ ǰȱ ȱȱ ǯȱ÷ȱ
ȱ
ȱ ȱ £ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ
ǻǼȱȱûȱȱȱǰȱȱȱȱȱǻȱȱȱûȱȱŚȱ
Ǽǯȱ
Programm
import java.io.*;
import java.util.*;
public class P9QuadrateRek {
private static final String FileInputName = "quadrate.in";
private static final String FileOutputName =
"quadrate.out";
private int step = 0;
private boolean inSquare(int x0, int y0,
int cx, int cy, int k){
int x1 = cx - k;
int x2 = cx + k;
int y1 = cy - k;
int y2 = cy + k;
return (x1 <= x0 && x0 <= x2 &&
y1 <= y0 && y0 <= y2);
}
public void count(int x0, int y0, int cx, int cy, int k) {
int x1, x2, y1, y2;
if(inSquare(x0, y0, cx, cy, k)) this.step++;
if(k>1){
ȱ£ ȱDZȱ
x1 = cx - k;
dzȱ
x2 = cx + k;
if(inSquare(x0, y0, x1, y1, k))
y1 = cy - k;
count(x0, y0, x1, y1, k/2, n);
y2 = cy + k;
if(inSquare(x0, y0, x1, y2, k))
count(x0, y0, x1, y1, k/2);
count(x0, y0, x1, y2, k/2, n);
count(x0, y0, x1, y2, k/2); if(inSquare(x0, y0, x2, y1, k))
count(x0, y0, x2, y1, k/2, n);
count(x0, y0, x2, y1, k/2);
count(x0, y0, x2, y2, k/2); if(inSquare(x0, y0, x2, y2, k))
count(x0, y0, x2, y2, k/2, n);
}
…
}
130
Grundlegende Algorithmen mit Java
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out= null;
try {
int k, x0, y0;
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName ));
while(sc.hasNextInt()) {
k = sc.nextInt();
x0 = sc.nextInt();
y0 = sc.nextInt();
P9QuadrateRek q = new P9QuadrateRek();
q.count(x0, y0, 1024, 1024, k);
out.println(q.step);
}
}
finally {
if (sc!=null) {
sc.close();
}
if(out!=null) {
out.close();
}
}
}
}
ȱ
Aufgabe
ȱȱȱȱȱ§ȱȱ§ȱȱǰȱȱȱ
ȱȱȱȱǯȱȱ
Problem 10. Quadrate (direkte
Rekursion)
ȱ ȱ ȱ ȱ ǰȱ ȱ
ȱȱǯȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱȱȱȱȱ §ȱ
ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
§ȱ ȦŘȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǯȱ
ûȱ ȱ ȱ ȱ ȱ §ȱ ȦŘȱ
5
Rekursion
131
£ȱȱȱŗŜȱȱȱ §ȱȦŚȱȱȱȱȱ ǰȱȱ
ȱ§ȱȱ ȱŗŖȱ¡ȱđȱ ǯȱȱ
ȱ
Programm
import java.awt.*;
import javax.swing.*;
public class P10PaintQuadrate extends JPanel{
private static final long serialVersionUID =
-3249277353528332376L;
public void paint(Graphics g) {
Dimension dim = this.getSize();
drawSquare(g, dim.width/2, dim.height/2,
Math.min(dim.width/2, dim.height/2));
}
private void drawSquare(Graphics g, int x, int y, int l)
if (l > 10) {
drawSquare(g, x-l/2, y-l/2, l/2);
drawSquare(g, x-l/2, y+l/2, l/2);
drawSquare(g, x+l/2, y-l/2, l/2);
drawSquare(g, x+l/2, y+l/2, l/2);
g.drawRect(x-l/2, y-l/2, l, l);
}
}
{
public static void main(String args[]) {
JFrame frame = new JFrame("Rekursivitaet Beispiel");
P10PaintQuadrate quadratePanel = new P10PaintQuadrate();
frame.getContentPane().add(quadratePanel);
quadratePanel.setPreferredSize(new Dimension(400, 400));
frame.pack();
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE);
Dimension screenDim =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameDim = frame.getSize();
frame.setLocation
((screenDim.width-frameDim.width)/2,
(screenDim.height-frameDim.height)/2);
frame.setVisible(true);
}
}
ȦȦȱ£ȱȱ
132
Grundlegende Algorithmen mit Java
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ŗȱ ȱ
ȱ ȱȱȱȱãđȱǯȱ
ȱȱǰȱ ȱ ȱȱ£ȱ
ǯȱ ȱ
ȱprivate static final long serialVersionUID =
-3249277353528332376L;
ȱ
ȱȱȱȱȱȱȱȱǯȱȱǰȱ ȱ ȱȱȱãǵȱ
řǯ £ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱǻȱŘǼǯȱ ȱȱȱȱȱ£ȱȱ
ȱ ǰȱ ȱ §ȱ ȱ ȱ đȱ ȱ ȱ ȱ ȱ Ȭ
ǯȱ
ȱ
ȱ
ȱ
ȱ
ȱŗȱ
ȱ
Śǯ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱŘȱ
ȱ
ȱ ȱ ȱ ȱ ȱ Ȭ ȱ ûȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǯ ǯȱ ȱ ¡ǯ ǯ ǯȱ ȱ ǰȱ ȱ ȱ
ȱȱȱ ȱȱȱ£ȱ ǯȱ
5
Rekursion
133
Problem 11. Quadrate und Kreise (indirekte Rekursion)
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ǯȱ
ȱȱ
Problemanalyse
und
Entwurf
der
Lösung
ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ
£ȱ ȱ ȱ ȱ ȱ ȦŘȱ ǰȱ ȱ
ȱȱȱȱǯȱȱ
ȱȱǰȱȱȱ ȱȱ ȱȱ
ȱȱǰȱȱȱȱ
ǯȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
§ȱȱ ȱȱȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ
ȱ £ȱ ǯȱ ȱ ȱ ȱ
ȱ ȱ ǰȱ ȱ ȱ §ȱ ŗȱ ȱ
ȱȱǯȱ
ȱ
Programm
import java.awt.*;
import javax.swing.*;
public class P11PaintQuadrateCircle extends JPanel {
private static final long serialVersionUID =
-6741198167758549984L;
public void paint(Graphics g) {
Dimension dim = this.getSize();
drawSquare(g, dim.width / 2, dim.height / 2,
Math.min(dim.width / 2,dim.height / 2));
}
private void drawCircle(Graphics g, int x, int y, int r) {
if (r > 25) {
g.drawOval(x-r/2, y-r/2, r, r);
drawSquare(g, x, y, r);
}
}
134
Grundlegende Algorithmen mit Java
private void drawSquare(Graphics g, int x, int y, int l) {
if (l > 1) {
g.drawRect(x-l/2, y-l/2, l, l);
drawCircle(g, x-l/2, y-l/2, l/2);
drawCircle(g, x-l/2, y+l/2, l/2);
drawCircle(g, x+l/2, y-l/2, l/2);
drawCircle(g, x+l/2, y+l/2, l/2);
}
}
public static void main(String args[]) {
JFrame frame = new JFrame("Rekursivitaet Beispiel");
P11PaintQuadrateCircle quadratePanel =
new P11PaintQuadrateCircle();
frame.getContentPane().add(quadratePanel);
quadratePanel.setPreferredSize(new Dimension(400, 400));
frame.pack();
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE);
Dimension screenDim =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameDim = frame.getSize();
frame.setLocation((screenDim.width - frameDim.width) / 2,
(screenDim.height - frameDim.height) / 2);
frame.setVisible(true);
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱ §ȱȱ ǯȱ
ȱȱȱǰȱȱȱȱȱ ǰȱȱȱ
ȱDZȱȱ
Ȭ ȱȱ ȱȱȱ ȱȱǻ£ȱ ȱ ȱ
ȱȱȦŘǰȱȱȱȱȱȱǼǰȱȱ
Ȭ ȱ ȱ ȱ ȱ ȱ ǻ£ȱ ȱ ȱ ȱ
ȱȱǰȱȱȱȱ ȱ£ȱ ȱȱȬ
ȱȱȱǼǰȱȱ
Ȭ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻ£ȱ ȱ ȱ
ȱȱȱȱ£ȱȱȱ§ȱȦŘǼǯȱ
ȱ
5
Rekursion
135
Problem 12. Die Koch’sche Schneeflockenkurve
ȱ Ȭ ȱ ȱ ŗşŖŚȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǻŗŞŝŖȬŗşŘŚǼȱ ûǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
Ȭ ȱ ȱȱȱȱ £ȱǯȱȱȱȱȱȱ ȱ
ǰȱȱȱȱ ȱȱȱȱȱȱ ȱȱȱȱȱ
ȱ ûȱ ûȱ ȱ ȱ ûȱ ȱ ȱ Ǯȱ ȱ ȃȱ ǰȱ
ȱȱȱ£DZȱ
ȱ
ȱ
ȱ ȱȱ Ȭ ȱȱȱȱǯȱȱ
ȱȱȱãȱȱȱ£ȱȱȱȱȱȱŚǯȱ
ȱ
ȱ
ȱȱȱǰȱ ȱȱȱ £ȱȱȱȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭ
ǰȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ £ǯȱ ȱǻȱ
ǯǼDZȱ
ȱ
ȱ
ȱƽȱŗȱ
ȱƽȱŘȱ
136
Grundlegende Algorithmen mit Java
ȱƽȱŚȱ
ȱƽȱŜȱ
Problemanalyse und Entwurf der Lösung
ȱ
0
xA
yB
Q
xN
xM
xB
ż
x
B
D
N
yN
C
yM
yA
A
ż
P
M
y
ȱ
ûȱȱȱȱ ȱȱȱȱȱȱȱ ȱ ȱ ǻ¡ǰȱ¢Ǽȱȱ
ǻ¡ǰȱ¢Ǽȱûȱ ȱȱ ȱȱȱ ǰȱȱȱȱȱȱȱȬ
DZȱ
ȱ
ǰȱȱ∈ȱǰȱ AC ȱǓȱ CD ȱǓȱ DB ȱǓȱ CM ȱǓȱ MD ȱǯȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ȱ
ȱ£ȱȱȱȱȱ AB ȱȱǻ¡ǰȱ¢Ǽǯȱȱ ȱ
ȱȱDZȱ
ȱ
5
Rekursion
137
xN =
x A + xB
,
2
yN =
y A + yB
ǯȱ ȱ
2
ȱ
ȱ
ȱ
ȱȱ ȱȱ ȱȱȱǯȱȱDZȱ
ȱ
2 x + xB
xC − x A 1
ǰȱ
= 3 xC − 3x A = xB − x A xC = A
3
xB − x A 3
yC − y A 1
2 y + yB
= 3 yC − 3 y A = y B − y A yC = A
ǯȱȱ
yB − y A 3
3
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱ£DZȱȱ
xD =
x A + 2 xB
y + 2 yB
und y D = A
ǯȱȱ ȱ
3
3
ȱ
ȱ
ȱȱȱȱȱȱȱ§ȱ
ȱ
ȱ
AB
ȱȱȱ ãȱ MN ȱǰȱ
3
DZȱ
ȱ
MN = CM ⋅ sin
π
3
=
AB 3
3
⋅
=
⋅ AB ǯȱȱ
3
2
6
ȱ
ȱǰȱżȱ = ȱǻȱȱȱȱȱȱȱȱ
ȱDZȱȱ±ȱȱ±Ǽǯȱ ȱȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ sin α =
y A − yB
AB
und cos α =
xB − x A
AB
ǯȱ ȱ
ȱ
ȱ
ȱ ȱ ȱȱȱȱDZȱ
ȱ
ȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱ ∆x = MN ⋅ sin α =
y − yB
3
3
⋅ AB ⋅ A
=
⋅ ( y A − yB ) ȱ
6
6
AB
ȱȱȱȱȱȱȱȱȱ ∆y = MN ⋅ cos α =
3
3
x − xA
⋅ AB ⋅ B
=
⋅ ( xB − x A ) ǯȱ
6
6
AB
ȱ
ȱ
ȱ
ȱ
ȱȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
138
Grundlegende Algorithmen mit Java
ȱȱȱ ȱȱȱDZȱ
ȱ
ȱȱȱȱ
ȱ
xM = xN + ∆x =
x A + xB
3
+
⋅ ( y A − yB ) ȱȱȱȱ
2
6
ȱ
ȱ
ȱ
ȱ
yM = y N + ∆y =
y A + yB
3
+
⋅ ( xB − x A ) ǯȱȱ
2
6
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱ
ȱ
ȱãȱ ȱȱǽşşǾȱ§ǯȱȱ
ȱ
Programm
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class P12Koch extends JPanel {
private static final long
serialVersionUID = 7412004320518032437L;
private static final double Sqrt3 = Math.sqrt(3.0);
private static final double Sqrt3Div6 = Math.sqrt(3.0) / 6.0;
private static final String FileInputName = "iteration.in";
private int iterations;
public P12Koch(int numIterations) {
this.iterations = numIterations;
}
public void paint(Graphics g) {
Dimension rect = this.getSize();
int diff = rect.width - rect.height;
PaintInvariant paintInv = new PaintInvariant(g, 5);
int l;
if (diff < 0) {
diff *= -1;
l = rect.width / 2;
paintInv.dx = 0;
paintInv.dy = diff / 2;
} else {
5
Rekursion
139
l = rect.height / 2;
paintInv.dx = diff / 2;
paintInv.dy = 0;
}
double xa, ya, xb, yb, t = l;
xa = l;
ya = l - t;
xb = l - Sqrt3 * t / 2;
yb = l + t / 2;
drawKoch(paintInv, this.iterations,
(int) xa, (int) ya, (int) xb, (int) yb);
xa = l + Sqrt3 * t / 2;
ya = l + t / 2;
drawKoch(paintInv, this.iterations,
(int) xb, (int) yb, (int) xa, (int) ya);
xb = l;
yb = l - t;
drawKoch(paintInv, this.iterations,
(int) xa, (int) ya, (int) xb, (int) yb);
}
private void drawKoch(PaintInvariant paintInv, int n,
double xa, double ya, double xb, double yb) {
if (n > 1) {
double xc, yc, xm, ym, xd, yd;
xm = (xa + xb) / 2 + Sqrt3Div6 * (ya - yb);
ym = (ya + yb) / 2 + Sqrt3Div6 * (xb - xa);
xc = (2 * xa + xb) / 3;
yc = (2 * ya + yb) / 3;
xd = (xa + 2 * xb) / 3;
yd = (ya + 2 * yb) / 3;
drawKoch(paintInv, n - 1, xa, ya, xc, yc);
drawKoch(paintInv, n - 1, xc, yc, xm, ym);
drawKoch(paintInv, n - 1, xm, ym, xd, yd);
drawKoch(paintInv, n - 1, xd, yd, xb, yb);
} else {
paintInv.g.drawLine(
(int) xa, (int) ya, (int) xb, (int) yb);
}
}
public static void main(String args[]) throws IOException {
Scanner sc = new Scanner(new File(FileInputName));
int numIterations;
try {
numIterations = sc.nextInt();
140
Grundlegende Algorithmen mit Java
JFrame frame = new JFrame("Rekursivitaet Beispiel");
P12Koch quadratePanel = new P12Koch(numIterations);
frame.getContentPane().add(quadratePanel);
quadratePanel.setPreferredSize(new Dimension(400, 400));
frame.pack();
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE);
// Frame auf den Bildschirmmittelpunkt einstellen
Dimension screenDim =
Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameDim = frame.getSize();
frame.setLocation((screenDim.width - frameDim.width) / 2,
(screenDim.height - frameDim.height) / 2);
// den Frame anzeigen
frame.setVisible(true);
} finally {
sc.close();
}
}
}
class PaintInvariant {
Graphics g;
int dx, dy, minL;
PaintInvariant(Graphics g, int minL) {
this.g = g;
this.minL = minL;
}
}
Aufgaben
ŗǯ
Řǯ
ȱȱ§ǰȱȱȱ Ȃȱȱûȱȱȱ Ȭ
ȱȱđǯȱȱȱȱȱ§ȱǯȱȱȱȬ
£ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ £ ȱ ȱ ȱ §ȱ
ȱǰȱȱȱȱȱȱ£ȱ§ǯȱȱ
ȱȱȱûȱȱǯȱȱ
Ȭǯȱȱ ȱ ȱȱǯȱ ȱ ȱȱȱ
ȱ £ȱȱ ȱ ǰȱȱȱȱȱȱǯȱ
5
Rekursion
141
ȱ ȱ ȱ ȱ đȱ ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ûȱ ȱ ǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ Ȭ
ǯȱDZȱ
ȱ
ȱƽȱŗȱ
ȱƽȱřȱ
ȱƽȱśȱ
ȱƽȱŝȱ
ȱ
řǯ
ȱȱûȱȱȱ ȱȱȱ§ȱȱȬ
ǯȱȱȱ §ȱȱȱȱȱȱȱ
§ȱǯȱȱȱȱȱ§ȱûȱȱǰȱȱȱȬ
ȱȱ§ǯȱ
ûȱȱǻǯȱȬȱǼǯȱȱȱȱȱǻŖǰȱŗǼȱƽȱǿǻ¡ǰȱ
¢Ǽȱ ȩȱ Ŗȱ ǀȱ ¡ǰȱ ¢ȱ ǀȱ ŗȀȱ ǰȱ ǯȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱǻŖǰȱŖǼǰȱǻŖǰȱŗǼǰȱǻŗǰȱŗǼȱȱǻŗǰȱŖǼǯȱǽşřǾȱȱȱ
ȱȱǰȱ ȱȱ ȱȱǻŖǰȱŗǼȱȱȱûȱǯȱ
ȱȱȱȱ¢ȱDZȱ
ȱ
¡ȱ
ŗȱ
Řȱ
řȱ
Śȱ
ȱ
ȱ
Ŗȱ
Ŗǯśȱ
Ŗǯśȱ
Ŗȱ
ȱ
Ŗǯśȱ
Ŗȱ
Ŗȱ
ȬŖǯśȱ
ȱ
Ŗǯśȱ
Ŗȱ
Ŗȱ
ȬŖǯśȱ
ȱ
Ŗȱ
Ŗǯśȱ
Ŗǯśȱ
Ŗȱ
ȱ
Ŗȱ
Ŗȱ
Ŗǯśȱ
ŗȱ
ȱ
Ŗȱ
Ŗǯśȱ
Ŗǯśȱ
Ŗǯśȱ
142
Grundlegende Algorithmen mit Java
ȱȱ Ŗȱȱ ȱȱǻŖǰȱŗǼǯȱûȱȱûȱȱ Ŗȱ ȱȱ ȱ
Ƹŗȱȱȱ ȱ ȱ ǰȱȱȱȱȱȱ ȱȱȱȬ
ȱȱ£DZȱȱ
ȱ
ª x º ª an
wn « » = «
¬ y ¼ ¬ cn
bn º ª x º ª en º
fûȱȱƽŗǰȱdzǰȱŚǯȱ
+
d n »¼ «¬ y »¼ «¬ f n »¼
ȱ
ȱȱDZȱȱȱ
ȱ
­ xn ,i +1 = an ⋅ xi + bn ⋅ yi + en
fûȱȱƽŗǰȱdzǰȱŚǯȱȱ
®
¯ yn,i +1 = cn ⋅ xi + d n ⋅ yi + f n
ȱ
ȱȱûȱȱȱãđȱȱȱŖȱȱDZȱȱ
ȱ
4
K i +1 =
{( x
n , i +1 , yn , i +1 ) ( xi , yi ) ∈ K i } ǯȱ
n =1
ȱ
ȱȱȱǰȱȱȱ ȱ Ŗȱ£ȱȱȱȬ
ȱ ŗŘȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ǯȱ tȱ ȱ
ȱȱȱȱǽŜŝǾȱȱ£§£ȱ ȱǯȱ
ȱ
ǯȱȱûȱ ȱ ŖDZȱȱ
ȱ
y 1
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
0
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
1
x
5
Rekursion
143
ȱ ȱ Ŗǰȱ ŗǰȱdzǰȱ ŗŗDZȱ
ȱ
ȱ
ȱ
ȱ
ȱ
§ȱȱȱ ǰȱûȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱđȱȱûȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȇȱ ȱ ȱ¢ȱȱȱ¢ǯȱ ȇȱȱ ȱȱǯȱȱ
ȱ Ȭ ȱ
Teile und Herrsche
6
ȱ
ȱ
ȱ
ȱ
ȱ
Grundlagen
ȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǻDZȱ ȱ ȱ Ǽȱ ȱ
ȱ £ãȱ ãȱ ȱ ǯȱ ǻŗŚŜŗȬŗŚŞřǼȱ ǯȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ §ȱ ǻŗŖŖȱ ǯȱ ǯȬŚŚȱ ǯȱ ǯǼȱ £ǯȱ ȱ ȱ ȱ ȱ
ǰȱȱȱȱ ȱȱȱ§ȱȱ ȱ §ȱȱȬ
ȱȱǰȱȱȱ£ȱȱȱûȱȱ£ȱǯȱ
ȱ
ȱȱǮȱȱ ȃȱȱȱ ȱ£ȱ ǯȱ
ȱȱȱǰȱđȱȱ¡ȱȱ £ ǯȱȱ £ȱ §ǰȱȬ
ȱ ȱȱȱȱȱ£ǰȱȱ ȱȱȱȱãȱãȬ
ȱȱȱ ǯȱȱȱȱȱȱ ȱđȱ
£ȱȱ ãǯȱȱDZȱ ȱ ȱȱ ȱ ȱûȱ
ȱ DZȱǮ£ ȱȱǷȱûȱǯȱȮȱȱȱǷȱȱ ǯȃȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ãȱ ȱ ãǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ §ȱ ȱ ȱ ǰȱ ȱ
ȱãȱ ȱãǯȱȱ
ȱ
ȱȱûȱȱãȱȱȱȱǮȱȱ ȃDZȱ
• DZȱȱȱȱȱȱǰȱȱȱȱȱ
ȱǰȱȱȱȱ£ȱãȱDzȱ
•
DZȱãȱȱDzȱ
•
DZȱ£ȱȱãȱ ȱ£ȱȱ ãȱ£ǯȱ
146
Grundlegende Algorithmen mit Java
ȱȱȱȱȱDZȱȱ
ȱ
ȏ ǻǰȱǰȱǼȱ
ȱȱȱȱ ȱǻ≤ŖȱǼȱȱȱ
ȱȱȱȱȱȱȱȱǻǰȱǰȱǼȱ
ȱȱȱȱȏ ȱ
ȱȱȱȱȱ¡ȱ
ȱȱȱȱȱȱȱȱǻǰȱǼȱȱǻŗǰȱŗǼǰȱǻŘǰȱŘǼǰȱdzǰȱǻǰȱǼȱ
ȱȱȱȱȱȱȱ ǻŗǰȱŗǰȱŗǼȱ
ȱȱȱȱȱȱȱ ǻŘǰȱŘǰȱŘǼȱ
ȱȱȱȱȱȱȱȱdzȱ
ȱȱȱȱȱȱȱȱ ǻǰȱǰȱǼȱ
ȱȱȱȱȱȱȱȱȱŗǰȱŘǰȱdzǰȱȱȱȱȱ
ȱȱȱȱȱȏȱ
ȱȏȱ ȏ ǻǰȱǰȱǼȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ ȱ ûȱ ȱ ȱ ȱ DZȱ ûȱ ȱ
ǯȱ
ǰȱ ǰȱ
Problem 1. Größter gemeinsamer Teiler mehrerer Zahlen
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ûȱ ǰȱ ȱ ȱ £Ȭ
ȱȱǯȱȱȱȱǰȱȱȱãđȱȱȱ
ǻǼȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ¡ǰȱ
ȱȱȱȱȱŖȱǯȱ
ȱ
ggt.in
Bildschirm
ggT = 5
45 60
125 345 65
9875 4555
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ¢ȱ ¢ǀ ǁǰȱ ȱ ȱ ȱ £ǯȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ £ ȱ §ȱ ȱ ȱ ȱ
ãȱȱȱȱ ãȱȱȱûȱȱȱȱ£ȱǯȱ
ȱȱȱǰȱ ȱȱȱȱȱȱȱǯȱ
ȱȱȱȱȱ ȱ§ǯȱȱ
ȱ
6
Teile und Herrsche
147
Programm
import java.io.*;
import java.util.*;
public class P01GGT {
private static final String FileInputName = "ggt.in";
private static int gcd(int a, int b) {
while (b != 0) {
ȏǻǰȱǼȱ
int r = a % b;
ŗǯ ŗȱbȱǰȱŗȱbȱǰȱȱbȱŗȱ
a = b;
Řǯ ȱǻȱ≠ȱŖǼȱȱ
b = r;
Řǯŗǯ ȱȱƸŗȱbȱȱ
}
ŘǯŘǯ ȱȱƸŗȱbȱȱǻƽȱȱǼȱ
return a;
}
ȱȱȱȱȱȱȱȱȱȱȱȱŘǯřǯȱȱȱȱȱȱȱȱbȱƸŗȱ
ȱȱȱȱȱȱȱȱȱȏȱ
ȱȱřǯȱǻǰȱǼȱƽȱȬŗȱ
private static int
divide_et_impera(List<Integer> a, int iMin, int iMax)
{
if (iMin < iMax) {
int middle = (iMin + iMax) / 2;
int d1 = divide_et_impera(a, iMin, middle);
int d2 = divide_et_impera(a, middle + 1, iMax);
return gcd(d1, d2);
}
return 0 <= iMin && iMin < a.size() ? a.get(iMin) : 0;
}
public static void main(String[] args) throws IOException {
List<Integer> list = new ArrayList<Integer>();
Scanner sc = new Scanner(new File(FileInputName));
try {
while (sc.hasNextInt()) {
list.add(sc.nextInt());
}
int sz = list.size();
if (sz > 0) {
System.out.println(
" ggT = " + divide_et_impera(list, 0, sz - 1));
}
} finally {
sc.close();
}
}
}
ȱ
148
Grundlegende Algorithmen mit Java
Aufgaben
ŗǯ
Řǯ
ȱȱȱǰȱȱȱ ȱ ǰȱȱȱ
ȱȱãđȱȱȱǯȱ£ȱǯȱ
ȱȱȱǰȱȱȱȱȱȱȱǯȱǰȱ
ȱȱȱȱȱȱǯȱ
Problem 2. Die Türme von Hanoi
ȱȱȱ£ȱȱȱȱ ȱŗŞŞřȱȱȱ ȱ§ȱ
ȱȱȱDZȱȱûȱȱ ǯȱȱȱȱȱûȱȬ
ȱȱ ȱȱȱǯȱȱȱȱȱȱ§ȱǰȱȱȱ
ǰȱ ȱ ȱ ȱ ȱ đȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱȱȱȱȱȱȱǰȱȱ ãđȱȱǰȱȱãđȱ
ȱȱǯȱ
ȱȱȱȱǰȱȱȱȬȱȱȱȱȱ£ȱ£ǰȱ Ȭ
ȱȱȱȱȱȱȱȱȱ ȱȱǯȱ
ȱȱȱDZȱ
ȱ
• ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ
• ȱȱȱãđȱȱȱȱȱȱȱ ȱ
A
B
C
ȱ
ȱ ȱ ûȱ ȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ
û£ȱ £ȱ ȱ ûǰȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ǯǰȱ ȱ ȱ
DZȱ
ȱ
Tastatur
3
ȱ
hanoi.out
(A,C)(A,B)(C,B)(A,C)(B,A)(B,C)(A,C)
6
Teile und Herrsche
149
Problemanalyse und Entwurf der Lösung
ȱãȱȱȱȱȱȱDZȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱ£ȱ£ǰȱȱȱ£ȱȬŗȱȱȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ ȱ ȱ ȱ →ȱ
ûȱȱȱȬŗȱȱȱȱȱȱȱȱȱȱȱȱǰȱ
ǯǯDZȱ
­ A → C , wenn n = 1
Hanoi ( n, A, C , B ) = ®
¯ Hanoi (n − 1, A, B, C ), A → C , Hanoi (n − 1, B, C , A), anderenfalls
Programm
import java.io.*;
import java.util.*;
public class P02Hanoi {
private static final String FileOutputName = "hanoi.out";
private PrintStream out;
P02Hanoi(PrintStream out) {
this.out = out;
}
private void write(char a, char b) {
out.print('(');
out.print(a);
out.print(',');
out.print(b);
out.print(')');
}
public void hanoi(int n, char a, char c, char b) {
if (1 == n)
write(a, c);
else {
hanoi(n - 1, a, b, c);
write(a, c);
hanoi(n - 1, b, c, a);
}
}
public static void main(String[] args) throws IOException {
PrintStream out = new
150
Grundlegende Algorithmen mit Java
PrintStream(new File(FileOutputName));
try {
System.out.print(" n = ");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
new P02Hanoi(out).hanoi(n, 'A', 'C', 'B');
} finally {
out.close();
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱǰȱȱȱ£ȱȱûȱ 2 n − 1 ȱǯȱ
ȱȱȱǰȱȱȱãȱȱȱȱãȱ
£ǯȱ
ȱ ȱ ȱ Ȭȱ ǰȱ ȱ ȱ ȱ ȱ Ȭ
ȱ£ȱȱûȱãDZȱ ȱȱȱȱǰȱȱȱȱȬ
ȱȱȱȱ£ȱǰȱȱȱȱȱȱȱ
ȱȱȱ§ȱȱȱȱ£¢ȱ£ȱdzȱȱȬ
ȱǮȃȱȱȱȱȱǰȱȱȱȱȱȱǻȱ
ȱȱȱȱǰȱȱȱȱȱãđȱȱȱǼǯȱ
ȱȱȱȱûȱȱǯȱ
ȱ ȱ ȱ ȱ 2 n − 1 ȱ ûȱ ȱ ȱ ǯȱ ȱ
ȱ ȱ ǰȱ ȱ ûȱ £ ȱ ȱ ȱ ȱ ǻŖ≤≤ŗŖŖǼȱ ȱ ȱ
ǻŖ≤≤ 2
n
− 1 ǼȱȱȬȱȱǯȱ
Problem 3. Integral mit Trapezregel
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ ȱ ȱ ȱ
§ȱ £ ȱ ȱ ¡Ȭȱ ȱ ȱ Ȭ
ǯȱȱȱȱȱȱȱȱ£ ȱȬ
ȱǰȱ£ȱȱ ȱȱǯȱȱ
ȱ
£ȱ
ȱ
ȱ
ȱ
ȱǰȱȱȱ ȱȱȬ
ȱȱ ȱǽǰǾȱǻȱȱȱ§ȱȱǼȱȬ
ȱ £§ǯȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ¡Ȭȱ
ȱȱ ȱȱȱȱȱ ȱȱ ǰȱȱȱ
ȱ£§ǯȱȱȱȱ§ȱ£ȱǰȱ£ȱȱȱ ȱ
ȱȱȱȱȱûȱȱ£ȱǯȱ
6
Teile und Herrsche
ȱȱ
b
151
1
³ 1 + x dx ȱȱ£ȱȱ£ǰȱ ȱȱ ãȱȱȬ
a
2
£ȱ £ȱ ȱ ȱ ƽŖǯŖŖŖŗȱ ȱ ǯȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǻǰȱ Ǽǰȱ ȬŘŖŖȱ ≤ȱ ǰȱ ȱ ≤ȱ ŘŖŖǰȱ ȱ ≤ȱ ǰȱ ȱ ȱ ǯȱȱ
ȱȱȱȱȱǯȱȱȱǯȱ
ȱ
integral.in
integral.out
0 1
I(0, 1) = 0.785383
90.09 123.45
I(90.09, 123.45) = 0.00299929
-45.6 23
I(-45.6, 23) = 3.07615
Problemanalyse und Entwurf der Lösung
ȱ§ȱȱ£ȱȱȱȱǻǰȱŖǼǰȱǻǰȱŖǼǰȱǻǰȱ
§ f (a ) + f (b) ·
¸ ǯȱȱ
2
©
¹
y
ǻǼǼȱȱǻǰȱǻǼǼȱDZȱȱȱ (b − a )¨
ȱȱȱȱ§£ȱȱȱ
ȱ ȱ ûȱ ȱ ǰȱ ȱ ȱ
§ȱȱȱ ȱãđȱȱȱȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ
ȱȱ£ȱ¡ǯȱ
ȱ
f(b)
f(x)
f(a)
x
a
b
Programm
import java.io.*;
import java.util.*;
public class P03Integral {
private static final String FileInputName = "integral.in";
private static final String FileOutputName = "integral.out";
private static final double EPS= 0.0001;
private static double f(double x) {
return 1 / (1 + x * x);
}
private static double integral(double a, double b) {
if (b - a > EPS) {
double c = (a + b) / 2;
return integral(a, c) + integral(c, b);
} else {
return (b - a) * (f(b) + f(a)) / 2;
}
}
152
Grundlegende Algorithmen mit Java
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(
new File(FileInputName)).useLocale(Locale.ENGLISH);
while (sc.hasNextDouble()) {
double a = sc.nextDouble();
double b = sc.nextDouble();
out.print("I(");
ȱ£DZȱ
out.print(a);
out.println("I("+a+", " + b +
out.print(", ");
") = "+ integral(a, b));
out.print(b);
out.print(") = ");
out.println(integral(a, b));
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ǻȱ Ȭ
£Ǽǯȱ
£ȱȱȱȱȱȬȬ ǰȱȱȱ ȱ£ȱ
ǯȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ £ ȱ ȱ ¡Ȭ
ȱȱȱȱȱȱ ǰȱȱȱ§Ȭ
ȱ£§ǯȱȱ ãȱȱȱûȱȱ ȱǽǰǾȱȱǻǻƸǼȦŘǼǯȱ
Problem 4. QuickSort
ȱȱȱǯȱȱȱȱûȱǯȱ ȱȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱǯȱDZȱ
ȱ
ȱ
ȱ
6
Teile und Herrsche
QSort.in
345 67 13 789 90 76 -45
153
QSort.out
-45 13 67 76 90 345 789
Problemanalyse und Entwurf der Lösung
ȱȱȱǰȱȱǯǯǯȱ ȱǻǯȱŗşřŚǼȱŗşŜŘȱȱǰȱȱ
ȱ£ȱǯȱȱȱȱǰȱ ȱđȱȱȱ
ȱǯȱȱȱȱȱȱȱȱȱǰȱȱ
ȱȬȱǻȱǼȱǯȱȱȱȱȱȱȱ£ ȱȬ
ȱǯȱȱȱȱȱȱȱãđȱȱȱȱȬǰȱȱ
ȱȱȱ£ ȱȱȱȱȱǻȱȱȱȱȱȬ
ȱȱȱǼǯȱȱȱȱȱȱȱȱ ȱȱȬ
ȱ ȱǰȱȱ£ ȱȱǰȱȱȱȱȱȱȱȱȬ
ǯȱȱȱǰȱȱȱȱȱȱȱǰȱ
ȱȱǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ȱ ȱ
ȱǽǾǰȱǽƸŗǾǰȱdzǰȱǽǾǰȱȱ ȱ ȱȱ§ȱȱȱǰȱȱ
ȱ ȱ ȱ ȱ ȱ £ ǯȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ £ ȱ
ȱ ȱ ȱ ǻȱ ȱ ȱ ȱ ãđȱ ȱ Ȭ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȬǼȱ £ȱ ȱ ȱ
Ȭȱ £ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ §ȱ ȱ ȱ ŗȱ ȱ
ǻƽǼǯȱ
ȱ
¡§ǯȱȱȱȱȱ£ ȱȱǰȱȱ ȱȱȱ
ǰȱȱȱȱ ¡§ȱȱȱǻȱȱǼǯȱȱûȱȱȱȱ
ǰȱ ȱ ȱ ȱ £ ȱ ȱ £ǰȱ ȱ ȱ ȱ ȱ §ȱ ȱ
ȱ ǯȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
ǯȱ ȱ ȱ ȱ §ǰȱ ȱ ȱ ȱ ȱ ȱ §ȱ
ȱȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P04QSort {
private static final String FileInputName = "QSort.in";
private static final String FileOutputName = "QSort.out";
private static void quickSort(int[] arr, int inf, int sup) {
154
Grundlegende Algorithmen mit Java
if (inf < sup) {
int pivot = arr[inf], aux;
int i = inf + 1, j = sup;
while (i <= j) {
while (i <= sup && arr[i] <= pivot)
i++;
while (j >= inf && arr[j] > pivot)
j--;
if (i < j && i <= sup && j >= inf) {
aux = arr[i];
arr[i] = arr[j];
arr[j] = aux;
i++;
j--;
}
}
i--;
arr[inf] = arr[i];
arr[i] = pivot;
quickSort(arr, inf, i - 1);
quickSort(arr, i + 1, sup);
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
List<Integer> list = new ArrayList<Integer>();
while (sc.hasNextInt()) {
list.add(sc.nextInt());
}
int idx = list.size();
int arr[] = new int[idx];
for(int i=0; i<idx; i++)
arr[i] = list.get(i);
quickSort(arr, 0, idx - 1);
for (int i = 0; i < idx; i++) {
out.print(arr[i]);
out.print(' ');
}
} finally {
if (sc != null) {
sc.close();
}
6
Teile und Herrsche
155
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
ȱȱȱȱȱȱȱûȱȱȱȱǻǯǼǯȱ
£ȱȱȱȱȱǰȱȱȱȬȱ£§ȱȱ
ȱ ȱȱ ǯȱ
ȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ Ȭȱ ȱ ǻŖ≤ȱ ǀǼȱ ȱ ǰȱ ȱ ¢ȱ ǰȱ ȱ
ȱȱ£ȱǯȱ
Problem 5. MergeSort (Sortieren durch Verschmelzen)
ȱȱȱǯȱȱȱȱûȱǯȱ ȱȱȱ
ȱǰȱȱȱȱȱȱȱǯȱȱȱȱȱ
ǯȱDZȱ
ȱ
MSort.in
MSort.out
345 67 13 789 90 76 -45
-45 13 67 76 90 345 789
ȱ
Problemanalyse und Entwurf der Lösung
ȱǰȱȱ ȱǰȱȱ£ȱǯȱȱȱ
ȱ ȱDZȱȱ¢ȱȱȱȱ ȱȱ£ ȱȱǰȱȱȱ ȱ
ȱȱǯȱđȱ ȱȱ£ȱȱȱ¢ȱȬ
£ǰȱ ȱ ȱ ȱ ¡§ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
¡§ȱȱȱȱȱǻȱȱǼǰȱȱ§ȱ£ȱȱȱ
§ȱȱȱǯȱ
ȱ
156
Grundlegende Algorithmen mit Java
Programm
ȱ
import java.io.*;
import java.util.*;
public class P05MergeSort {
private static final String FileInputName = "MSort.in";
private static final String FileOutputName = "MSort.out";
private static void mergeSort(int arr[]) {
if (arr.length <= 1)
return;
int v1[] = new int[arr.length / 2];
int v2[] = new int[arr.length - v1.length];
System.arraycopy(arr, 0, v1, 0, arr.length/2);
System.arraycopy(arr, arr.length/2, v2, 0,
arr.length-v1.length);
mergeSort(v1);
mergeSort(v2);
int i1 = 0, i2 = 0;
for (int k = 0; k < v1.length + v2.length;)
if ((i2 >= v2.length) ||
(i1 < v1.length && v1[i1] <= v2[i2])) {
arr[k++] = v1[i1++];
} else {
arr[k++] = v2[i2++];
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
6
Teile und Herrsche
157
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
List<Integer> list = new ArrayList<Integer>();
while (sc.hasNextInt()) {
list.add( sc.nextInt() );
}
int arr[] = new int[list.size()];
for(int i=0; i<list.size(); i++)
arr[i] = list.get(i);
mergeSort(arr);
for (int i = 0; i < arr.length; i++) {
out.print(arr[i]);
out.print(' ');
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgabe
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ DZȱ
¢ȱǰȱȱȱȱȱȱȱȱǰȱȱȱȱȱȱȱǰȱ£ Ȭ
ȱȱȱ¢ȱȱ DZȱ
private static void mergeSort(int arr[], int i, int j)..
Problem 6. Quad-Bäume
Ȭ§ȱȱ§ǰȱȱȱ ȱ¡ȱȱ ȱȱûǯȱȱ
ȱ ǯǯȱ £ȱ ȱ £ǯȱ ȱ ȱ Ȭ§ȱ ȱ £ȱ
Ȭ§ǰȱȱȱȱ ȱ ȱȱȱȱȱȱ ȱǯȱ
ȱȱȱȱ ȱûȱȱȱǯȱ
ȱ
ȱ£ȱȱ ȱȱǰȱȱȱȱȱȱȱȱǻȬ
Ǽȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ
ȱ ǯȱ ȱȱȱȱȬȱ ȱȱȱȱȱ£ȱ§Ȭ
ǰȱȱȱȱȱȱȱȱ ȱǻȱȱȱȬ
158
Grundlegende Algorithmen mit Java
Ǽǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ £ǰȱ Ȭ
ǯȱȱȱ ȱȱȱ ȱȱȱ£ǰȱ ȱȱȬ
ȱ ȱ §ǯȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ §ȱ
ȱǰȱǯǯȱȱ§ȱȱȱûȱȱȱȱȱȱǯȱ
ȱ
ȱȱȱ £ đȱȱȱřŘȱȱ£ȱȱǯȱȱ
ȱǮȄȱ£ ȱǰȱȱȱȱȱ£ȱ£ǯȱ ȱȱ ȱȱ
¡ȱ £ǰȱ ȱ ȱȱȱ ȱ¡ȱȱȱȱ £ȱ
ǯȱȱȱȱȱǰȱȱȱȱȱȱȱȱǰȱȱȱ
£ȱȱȱǯȱȱ ûȱȱȱǰȱȱȱ£ ȱȱȬ
ǰȱ ȱ £ȱȱȱȱ ǯȱ
ȱ
ȱȱȱȱǰȱȱȱȱȬȬȱ
£ ȱȱȱ£ȱȱ £ȱ¡ȱȱȱȱǯȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ £ȱ ȱ ȱ ȱ £Ȭ
ǰȱȱȱǰȱȱȱȱȬ§ǰȱȱȬȬȱǻ ȱȱ
§Ǽȱȱđȱȱ£ȱȱ £ȱ¡ǯȱ
ȱ
ȱ
ȱ
ȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ§ǰȱ ȱ ȱ
ȱȬȬȱ££ȱǯȱȱȱȱȱȱȱ
ǰȱ ȱ ȱ £ȱ ûȱ ȱ ȱ ȱ đȱ ûȱ ǯȱ ȱ ȱ
6
Teile und Herrsche
159
ȱȱûȱȱûȱȱȱȬǯȱDZȱȱȱȱȱȱ
ǯȱûȱȱȱȱȱǰȱ ȱȱDZȱ
quad.in
quad.out
ppeeefpffeefe pefe- ppeeefpffeefe + pefepeefe = ppeeefffpeefe
448 + 320 = 640
peefe
------------------------------------peeef + peefe = peeff
peeef
256 + 256 = 512
peefe
------------------------------------peeef + peepefefe = peepefeff
peeef
256 + 128 = 384
peepefefe
------------------------------------ppeeefffpeefe + peepefeff = ppeeeffff
ppeeefffpeefe
640 + 384 = 832
peepefeff
------------------------------------e + pfffe = pfffe
e
0 + 768 = 768
pfffe
------------------------------------ǻǰȱȬȱǰȱŗşşŚȬŗşşśǰȱ£Ǽȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱ¢ǻǼȱȱûȱ£ ȱȱȬȬȱȬ
£ȱ Ȭ§ȱ ȱ Ǯȃȱ ǻ£ȱ £ȱ ¡Ǽȱ ȱ ȱ ȱ ǯȱ
ȱȱȱȱ§ȱȱ§ȱǰȱȱȱȱȱȱ ȱ
ǰȱȱ ȱȱ§ȱ¡ȱȱȱȱ ȱûȱȱȬ
ȱȱȱȱȱ ȱȱȱȱȱ£ ȱȱǻƽŗǰȱǯǯǯǰŚǼȱȱ
ǯȱ ȱ ȱ ȱ £ȱ ¡ǰȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǰȱ£ȱ ȱȱDZȱ
ȱ
private static int
subTree(StringBuilder ss, StringBuilder sr, int t) {…}
ȱ
ȱȱȱȱȱǰȱȱȱ£ûȱȱȱȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ §ǰȱ §ǯȱ ȱ ȱ
ȱ ȱȱȱȱȱǯȱ ȱȱȱȱȱ ȱȱ
£ȱȱ ǰȱȱȱ£ȱȱǯȱ ȱȱǰȱ ȱ ǰȱȱȱȱ
ȱ ǯȱ ȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ Śȱ ȱ ǰȱ ǯǯȱ ȱ
ȱ Śȱ £ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ǰȱ ȱ ȱ ȱ ŗȱ ȱ
ȱǯȱ ȱ£§ȱ ȱ ȱřȱ£ȱ ȱ£ǯȱȱȱȱȱ
ȱȱȱ ǰȱȱ ȱȱȱȱŗǯȱȱȱ
ȱ
160
Grundlegende Algorithmen mit Java
Programm
import java.io.*;
import java.util.*;
public class P06QuadTree {
private static final String FileInputName = "quad.in";
private static final String FileOutputName = "quad.out";
private StringBuilder unifiedTree;
P06QuadTree() {
this.unifiedTree = new StringBuilder();
}
private static boolean isLeaf(char c) {
return 'e' == c || 'f' == c;
}
public void unifyTrees(StringBuilder t1, StringBuilder t2) {
if ('p' == t1.charAt(0) && 'p' == t2.charAt(0)) {
this.unifiedTree.append('p');
int i1 = 1, i2 = 1;
StringBuilder sr1 = new StringBuilder();
StringBuilder sr2 = new StringBuilder();
for (int i = 0; i < 4; i++) {
i1 = subTree(t1, sr1, i1);
i2 = subTree(t2, sr2, i2);
this.unifyTrees(sr1, sr2);
}
;
} else if (t1.charAt(0) == 'f' || t2.charAt(0) == 'f')
this.unifiedTree.append('f');
else if ('e' == t2.charAt(0))
this.unifiedTree.append(t1);
else if ('e' == t1.charAt(0))
this.unifiedTree.append(t2);
}
private static int
subTree(StringBuilder ss, StringBuilder sr, int t) {
sr.setLength(0);
if ('p' == ss.charAt(t)) {
for (int n = 1; n != 0 && t < ss.length();) {
if (isLeaf(ss.charAt(t)))
n--;
else
n += 3;
sr.append(ss.charAt(t++));
6
Teile und Herrsche
}
} else {
sr.append(ss.charAt(t++));
}
return t;
}
private static int getValue(StringBuilder ss, int v) {
if ('p' == ss.charAt(0)) {
StringBuilder sr = new StringBuilder();
int t = 1;
int suma = 0;
for (int i = 0; i < 4; i++) {
t = subTree(ss, sr, t);
suma += getValue(sr, v / 4);
}
return suma;
} else
return 'f' == ss.charAt(0) ? v : 0;
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNext()) {
StringBuilder t1 = new StringBuilder(sc.next());
StringBuilder t2 = new StringBuilder(sc.next());
P06QuadTree p6 = new P06QuadTree();
p6.unifyTrees(t1, t2);
out.printf("%s + %s = %s\n", t1, t2, p6.unifiedTree);
out.printf("%d + %d = %d\n", getValue(t1, 1024),
getValue(t2, 1024),
getValue(p6.unifiedTree, 1024));
out.println("-------------------------------------");
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
161
162
Grundlegende Algorithmen mit Java
Aufgabe
ȱ §ȱȱǻǼȱȱȱǯȱȱȱûȱȱȬ
ȱȬȱȱ§ǰȱȱȱ £ȱ¡ȱǯȱ
ȱ
Problem 7. Diskrete Fourier-Transformation (DFT)
ȱȱȬȱȱȱ ȱ£ȱȱȱȬ
ȱȱ ȱ£ȱ ȱȱȱȱȱȱ£Ȭ
ȱ ǯȱ ȱ ȱ řȬ ȱ £ȱ ȱ £ȱ Ȭ
ǯȱ ȱ ȱ £ȱ ȱ ȱ ûȱ ȱ ǰȱ
ȱ ȱûȱǰȱǰȱȬȱȱȱǻǼȱǯȱȱȱȱȬ
ǰȱ ȱ ȱ ȱ Ȭȱ ȱ
£ȱ
a = (a0 , a1 ,..., an−1 ) ǯȱ
ȱ
ȱȱȱȱ ωn0 , ωn1 , ωn2 ,..., ωnn −1 ȱȱ£ȱȱ X n − 1 = 0 ǻ £Ǽǯȱ
ȱ ȱ ȱ ¢ȱ P ( x) =
n −1
¦ a ⋅ x ǯȱ ȱ ȱ Ȭȱ
j
j
j =0
ȱȱȱȱ y = ( P (ω
ω
0
n ), P (
ω nn−1 )) ǯȱȱȱȱ¢ƽǻǼǯȱ
1
n ),..., P (
DZȱ ȱȱȱǯȱȱȱȱ £ȱǰȱȱȬ
ȱȱ¡ȱȱǻȱȱȬȱȱ §ȱȱȱǼȱȬ
ȱǯȱȱ£ȱȱȱȱȱȱȱȱ£ȱȱŘǯȱDZȱȬ
ȱȱȱǯȱȱȱȬȱȱ¢ȱûȱǯȱ
fourier.in
3.45 2.1
0.8 7.6
-5.4 3.1
-7.4 2.1
7.6 43.21
6.54 32.1
8.76 43
3.12 -3.21
ȱ
fourier.out
17.47 130
52.6993 -87.8464
-33.12 10.83
-33.8606 -17.3687
11.35 52.82
18.8007 -22.6936
48.5 -12.41
-54.2394 -36.5313
Problemanalyse und Entwurf der Lösung
ȱȱȱȱȱ£ȱǻŘǼǯȱ ȱȱȱ £ǰȱ§ȱȱȱȱ
DZȱ ȱ ȱ ǻȱ ȱ Ǽȱ ȱ ȱ ȱ Ȭȱ ȱ
ǻǯȱȱȱǼǯȱȱ
6
Teile und Herrsche
163
ȱȱ£ȱȱȱȱ Ȭ£ǯȱȱȱȱ£ ȱȱ¢ȱ
Ŗǻ¡Ǽȱȱŗǻ¡Ǽȱȱ ȱȦŘǰȱȱȱȱȱ ȱȱ Ȭ
£ȱȱǻ¡Ǽȱȱ£ȱȱ£ȱ ¡ȱȱDZȱ
A0 ( x) = a0 + a 2 x + a4 x + ... + an − 2
2
A1 ( x) = a1 + a 3 x + a5 x + ... + an −1
2
n
−1
x2 ,
n
−1
x2
ȱȱȱȱȱȱȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻŗǼȱ
ȱ
ȱDZȱȱ P ( x) = A0 ( x 2 ) + xA1 ( x 2 ) ȱ ȱ
ǻ¡Ǽȱȱ ȱȱȱȱ ωn0 , ω n1 , ω n2 ,..., ωnn−1 DZȱ
ŗǯ
ȱ ȱ Ŗǻ¡Ǽȱ ȱ ŗǻ¡Ǽȱ ǻ ȱ ȦŘǼȱ ȱ ȱ ȱ
(ω ) , (ω ), (ω ) ,..., (ω ) ǯȱ
0 2
n
1
n
2 2
n
n −1 2
n
Řǯ ȱȱǻ¡ǼȱȱǻŗǼǯȱ
ȱȱȱȱDZȱ
ȱ
ȏǻȱǼȱ
ȱ
ŗǯ ȱ←ȱ£ǻǼȱ
ȱ
Řǯ ȱǻƽŗǼȱȱȱȱ
ȱ
2π
2π
ȱ
řǯ ωn ← cos
ȱ
+ i sin
ȱ
n
n
ȱ
Śǯ ω ← 1 ȱ
ȱ
śǯ A0 ← ( a0 , a2 ,..., an − 2 ) ȱ
ȱ
Ŝǯ A1 ← ( a1 , a3 ,..., an −1 ) ȱ
ȱ
ŝǯ Ŗȱ←ȱ ȏǻŖǼȱ
ȱ
Şǯ
ŗȱ←ȱ ȏǻŗǼȱ
ȱ
şǯ ȱǻ←ŖDzȱ≤ȦŘȬŗDzȱȱŗǼȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ yk ← Y0 ( k ) + ω ⋅ Y1 ( k ) ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ y n ← Y0 ( k ) − ω ⋅ Y1 ( k ) ȱ
k+
ȱ
2
ȱ
ȱȱȱȱȱȱȱ ω ← ω ⋅ ωn ȱ
ȱ
ȏȱ
ȱ
ȱȱȱȱŗŖǯȱȱ¢ȱ
ȱ
ȏ ȱȏǻȱǼȱ
ȱ
ȱ
ȱ ȱ ¡ȱ ȱ £ǰȱ ȱ ȱ ȱ ȱ ¡ǯȱ ȱ Ȭ
ȱ ǻǼȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ȱ Ȭ
ȱ£ûǯȱȱ
164
Grundlegende Algorithmen mit Java
Komplexe Zahlen – kurze Einführung
§ȱȱǯȱȱȱȱ ȱ£ȱȱȱûȱȱȬ
ȱ ȱ ǻŗŝŖŝȬŗŝŞřǼȱ ûǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱ¡ŶȱƸȱ¡ȱƸȱȱƽȱŖȱȱǻȱǰȱ∈ȱ[ȱ ȱȱ≠ȱŖǼǰȱȱȱȱ[ȱãȱǰȱ£ȱãǯȱ
ȱ§ȱȱȱǻȱȱǼȱȱȱȱȱȱ §ȱãȱȱ
ȱȱ¡ŶȱƽȱȬŗǰȱȱȱȱŘȱƽȱȬŗǯȱȱ
ȱ ȱ ǻǼȱ ǯȱ ȱ ¡ȱ ȱ
ȱȱȱ£ȱƽȱ¡ȱƸȱ⋅¢ǰȱ ȱ¡ȱȱ¢ȱȱȱǯȱȱ
ȱȱDZȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ x = Re(z ) ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱȱ£Ǽȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ y = Im(z ) ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱǻ §ȱȱ£Ǽȱ
z = x − iy ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱǻ ȱȱ£Ǽȱ
ȱz =
x 2 + y 2 ȱ ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱȱ£Ǽȱ
ȱ
ȱ
ȱ
z1 + z 2 = ( x1 + x2 ) + i ( y1 + y2 )
z1 − z 2 = ( x1 − x2 ) + i ( y1 − y2 )
z1 ⋅ z 2 = ( x1 x2 − y1 y2 ) + i ( x1 y2 + x2 y1 )
z1 ( x1 x2 + y1 y2 ) + i ( x2 y1 − x1 y2 )
=
z2
x22 + y22
§z · z
2
z = z , z ⋅ z = z , z1 ± z 2 = z1 ± z 2 , z1 ⋅ z 2 = z1 ⋅ z 2 , ¨¨ 1 ¸¸ = 1
© z2 ¹ z2
z
z
z1 − z 2 ≤ z1 ± z 2 ≤ z1 + z 2 , z1 ⋅ z 2 = z1 ⋅ z 2 , 1 = 1
z2
z2
ȱ
ȱȱ£ ȱ¡ȱȱ£ŗƽȱ¡ŗȱƸȱ¢ŗǰȱ£Řȱƽȱ¡ŘȱƸȱ¢Řȱȱ¡ŗǰȱ¡Řǰȱ¢ŗǰȱ¢Řȱ∈ȱ[ǯȱ ȱ
ȱȱȱȱȱãȱȱûȱ¡ȱȱȱ
ȱȱȱ DZȱ
ȱ
§ȱȱȱȱ[ȱȱȱȱȱȱȱȱ§ǰȱ
ȱȱȱȱPȱȱ¡ȱȱȱȱǻ¡ȱǰȱđȱ
6
Teile und Herrsche
165
Ǽȱ ǯȱ ȱ ȱ ȱ Ȉȱ Ȉȱ ȱ Pȱ ȱ
£ ȱȱǯȱȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P07Fourier {
private static final String FileInputName = "fourier.in";
private static final String FileOutputName = "fourier.out";
private static List<Complex> fft(List<Complex> a) {
int n = a.size();
if (n <= 1)
return a;
Complex wn = new Complex(Math.cos(2 * Math.PI / n),
Math.sin(2 * Math.PI / n));
Complex w = new Complex(1.0, 0.0);
List<Complex> a0 = new ArrayList<Complex>();
List<Complex> a1 = new ArrayList<Complex>();
List<Complex> y = new ArrayList<Complex>();
for (int i = 0; i < n; i++) {
Complex c = a.get(i);
if (i % 2 == 0)
a0.add(c);
else
a1.add(c);
y.add(new Complex(0, 0));
}
List<Complex> y0 = fft(a0);
List<Complex> y1 = fft(a1);
for (int i = 0; i < n / 2; i++) {
Complex aux = w.multiply(y1.get(i));
y.set(i, y0.get(i).add(aux));
y.set(i + n / 2, y0.get(i).substract(aux));
w = w.multiply(wn);
}
return y;
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new
166
Grundlegende Algorithmen mit Java
File(FileInputName)).useLocale(Locale.ENGLISH);
List<Complex> a = new ArrayList<Complex>();
while (sc.hasNextDouble()) {
double re = sc.nextDouble();
double im = sc.nextDouble();
a.add(new Complex(re, im));
}
List<Complex> y = fft(a);
for (Complex c : y) {
out.println(c);
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
class Complex {
private double re, im;
Complex() {
this(0, 0);
}
Complex(double newRe, double newIm) {
re = newRe;
im = newIm;
}
public String toString() {
return this.re + " " + this.im;
}
public Complex add(Complex z) {
return new Complex(re + z.re, im + z.im);
}
public Complex substract(Complex z) {
return new Complex(re - z.re, im - z.im);
}
public Complex multiply(Complex z) {
return new Complex(re * z.re - im * z.im,
re * z.im + im * z.re);
}
}
6
Teile und Herrsche
167
Aufgabe
ȱȱȱȱȱȱȱȱȬȱûȱ
ȱȱ ȱȱ ȱȱȱȱǯȱȱȱ
ȱȱDZȱ
List<Complex> y = new ArrayList<Complex>();
w.setRe(1); w.setIm(0);
for(int k=0; k<n; k++){
Complex yk = new Complex(0, 0);
E.setRe(Math.cos(2*PI*k/n));
E.setIm(Math.sin(2*PI*k/n));
w.setRe(1); w.setIm(0);
for(int j=0; j<n; j++){
yk = yk.add(a.get(j).multiply(w));
w=w.multiply(E);
}
y.add(yk);
}
ȱȱǻǼȱȱ ǻǼȱȱȱȱȬȱûȱȱȱ£ ǯȱ
§ȱȱǯȱ
ȱ
ȱȱ £ȱȱ ȱȱȱȱǻǼȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱûǰȱȱȱǰȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
¢ȱȱǰȱǯǯǯȱȱȱ¢ȱȱȱǰȱȱ ǯȱ
ȱȱȱ
Backtracking
7
ȱ
ȱ
ȱ
ȱ
ȱȬȱȱȱǰȱȱȱȱȱȱȱãȬ
ǯȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ûȱ ûȱ ȱ ǰȱ ȱ
ȱȱȱȱǯȱ ȱȱȱȱDZȱǮȱȱȱ
ǰȱȱȱȱȱǰȱȱ ȱȱȱȱǰȱȱȱȱǷȃǯȱ
ȱ ȱ ȱȱȱûǰȱȱ£ȱǰȱȱȱ
ȱ£ȱãȱȱǯȱ
Problem 1. Das Problem der n Damen
ǯȱȱ¢ȱȱ¡ȱ££ȱǻŗŞŘŚȬŗŞŝŗǼȱȱȱȱȱ
Şȱ ȱ ŗŞŚŞȱ ȱ ȱ Ǯȱ £ȃȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ£ȱȱãȱãȱǯȱȱȱ ȱşŘȱ ȱȱ ȱ
ŗŞśŖȱ ȱ ǯȱ £ȱ ȱ ȱ ȱ Ȉ£ȱ ȱ Ȉȱ ȱ ǯȱ
ȱȱȱȱȱ đȱȱȱȱǰȱ ȱȱȱ§ȱ
ȱȱ£ûûǯȱȱ ȱǰȱȱ ȱ ǰȱ ȱȱãȱȱ
ȱȱûȱȱȱȱȱ×Ȭȱǰȱȱȱȱȱ
ǯȱ
ȱ ŗşşŗȱ ȱ ǯȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ
ȱ ȱǰȱǯȱŘǰȱǯȱŝȱǯȱȱŗşşŘȱȱãǰȱȱȱ
ȱȱ £ȱ£ ȱȱȱȱȱȱǯȱȱ
ǯȱȱȱȱȱȱȱ×ȱȱǯȱȱȱ
ȱãǰȱ ȱȱȱȱȱȱȱȱǰȱȱ
ȱȱȱȱȱǯȱ ȱȱȱȱǰȱ ȱ
ȱȱȱȱȱ ȱǰȱȱȱȱȱȬ
ǯȱȱȱǰȱȱŚȱ≤ȱȱ≤ȱŘŖǯȱ
DZȱ ûȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǯȱ DZȱ ȱ
ȱȱǯȱȱȱȱȱȱȱ ȱȱǯȱ ȱ
ȱ£ȱȱȱȱ£ȱȱȱȱȱ£ȱȱãȱǯȱ
ȱ
170
Grundlegende Algorithmen mit Java
Tastatur
n = 4
n = 8
nQueens.out
2 4 1 3
3 1 4 2
4 2
1 5 8 6 3 7 2 4
1 6 8 3 7 4 2 5
…
6 3 1 7 5 8 2 4
…
8 3 1 6 2 5 7 4
8 4 1 3 6 2 7 5
8 92
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱǰȱȱȱƽȱŚȱǯȱȱ ȱȱãȱǰȱ ȱȱȱ
ȱȱȱȱȱŚ×ŚȱȱȱǰȱȱȱȱȱȱȬ
ȱǯȱ
ȱȱ
ȱãȱ ȱǵȱȱ£ȱȱȱȱȱǻŗǰȱŗǼǰȱȱȱ
ȱȱ£ ȱȱȱȱ£ ȱȱ£ȱ£Dzȱ ȱǰȱȱȱȱ
ãȱȱȱȱ£ ȱȱȱȱȱȱȱǻŘǰȱřǼȱȱǻȱȱ
ȱȱȱȱȱȱǼǯȱ ȱ£ ȱȱ ȱ ȱ ȱ
ȱȱǻŘǰȱřǼǰȱȱȱŗǯȱȱ
ȱ
ȱȱ ȱǰȱȱȱȱãȱǰȱȱȱȱȱȱȱ£Ȭ
DZȱȱŗȱ ȱȱȱȱȱǰȱȱȱȱȱȱȱ
£ ȱȱȱȱȱȱŘǰȱřȱȱŚȱûȱǻȱŘǼǯȱȱȱȬ
ȱȱȱȱȱȱȱȱǰȱ ȱȱȱãȱ
£ȱǰȱȱȱȱǯȱ
ȱ
ȱ ȱ £ȱ £ ȱ ȱ £ûȱ ȱ ûȱ ȱ £ ȱ ȱ ȱ ȱ ȱ
ȱǻȱřǼǯȱ ȱȱȱȱȱȱ£ ȱȱǰȱȱȱȱ
ȱ£ȱȱǻȱŚǼǯȱȱ£ȱȱȱȱȱȱȱȱ
£ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ǻȬ
ȱśǼǯȱ
ȱȱȱǰȱȱ ȱȱ£ȱ§ȱȱûǰȱȱȱ
§ȱȱȱǮȃȱȱŘȱȱȱȱ£ȱǯȱȱ ȱ ȱ
ȱȱȱȱȱûǰȱ ȱȱřȱȱŚȱȱȱ£ ȱȱȱ
ǯȱȱȱ ȱ£ȱȱŘǰȱȱȱȱȱȱ£ȱǯȱ
ȱǰȱȱ ȱ£ȱȱȱ£ûȱûȱȱȱŘȱȱ§ȱȬ
ȱȱ£ȱǻȱŜǼǯȱûȱȱ£ ȱȱȱȱȱ£ ȱ
7
Backtracking
171
ȱȱȱ£ȱȱȱȱǻȱŝǼǯȱȱȱȱȱȱȱȱȬ
ȱȱȱȱȱ£ȱ ȱǻȱŞǼǯȱđȱȱûȱȱ£ȱ
ȱȱȱȱȱȱȱŚȱǻȱşǼǯȱȱȱȱȱȱ£ǰȱ
ȱ ȱȱȱãȱûȱȱǯȱȱ
ȱ
ȱȱãȱ ȱãȱ£ȱǰȱ ȱ ǰȱ ȱȱǰȱ Ȭ
ȱǯȱȱȱȱȱȱȱȱ£ȱãǰȱȱȱȱŗŖȱ
£ȱǯȱǻȱǰȱȱȱãȱȱȱȱȱãȱǼǯȱȱ
ȱ
ȱȱȱ§ȱãȱûȱȱȱŗŗȱȱȱȱȱȱ
Ŗȱȱȱãǯȱ ȱȱȱȱȱǰȱȱȱãȱûȱ
ȱƽȱŚȱ ȱǯȱ
ȱ
ȱ
ȱȱȱȱŗȱ ȱȱȱȱȱȱȱȱȱȱȱȱȱŘȱ
ȱȱȱȱȱȱȱřȱȱ
ȱŚȱ
ȱ
ȱȱȱȱśȱ ȱȱȱȱȱȱȱȱȱȱȱȱȱŜȱ
ȱȱȱȱȱȱȱȱȱȱȱȱşȱ
ȱ
ȱȱȱȱȱȱȱŝȱȱ
ȱȱȱȱȱȱȱȱȱŗŖȱ
ȱ
ȱŞȱ
ȱŗŗȱ
172
Grundlegende Algorithmen mit Java
ȱȱDZȱ
ȱ
ŗǯ ȱȱȱȱȱȱȱǯȱ
Řǯ ȱȱȱȱȱȱȱǯȱ
řǯ ȱãȱȱãȱȱȱȱ¢ȱ¡ǽǾȱȱȱȱ
DZȱ ¡ǽǾȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ £ǯȱ ȱ ȱ
ãȱȱ ȱȱȱ ¡ǽŚǾȱƽȱǿŘǰȱŚǰȱŗǰȱřȀȱǰȱȱ£ ȱãȱȱ
¡ǽŚǾȱƽȱǿřǰȱŗǰȱŚǰȱŘȀǯȱȱȱ §ǰȱȱȱȱȱȱȱ
ȱȱǯȱ
Śǯ ȱ ãȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǰȱDZȱ¡ǽǾȱ≠ȱ¡ǽǾȱǻȱȱûȱȱǼǯȱ
śǯ ûȱ£ ȱȱ ȱȱǰȱȱ ǀȱǰȱȱȱ ȱãȱDZȱȱûȱ
ȱȱȱȱȱȱǯȱȱãȱȱȬ
ȱãȱDZȱ
ȱ
ȱ
ȱ
¡ǽǾ
ȱ
¡ǽǾ
¡ǽǾȱ
¡ǽǾ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
-
ȱȱȱȱȱDZȱ j − i = x[i ] − x[ j ] ȱ
-
ȱ£ ȱȱȱȱDZȱ j − i = x[ j ] − x[i ] ȱ
ȱ
ȱ ȱȱȱȱǰȱȱ DZȱ
j − i = x[i ] − x[ j ] ǯȱ
ȱ
ȱ
ȱ
7
Backtracking
173
ȱȱȱȱȱȱȱ DZȱ
ȏȏȱ
ȱ←ȱŗȱ
ȱ¡ǽŗǾȱ←ȱŖȱ
ȱǻȱǁȱŖǼȱ¡ȱȱ
ȱȱȱȱȱȱ←ȱȱȱ¢ȱȱȱȱȱǰȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱŗǰŘǰȱǯǯǯǰȱȬŗȱ§ȱ
ȱȱȱȱȱȱ ȱǻȱ¡Ǽȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ǽǾȱ←ȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱ ȱǻȱƽȱǼȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱǯǯǯǰȱ¡ǽǾǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȏ ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱ ȱǻȱǀȱǼȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ←ȱȱƸȱŗȱȱȱȱȱȱȦȦȱȱȱȱǻ Ǽȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ǽǾȱ←ȱŖȱȱȱȱȱȱȱȱȱȱȱȦȦȱ ȱ£ȱȱȱȱŖȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȏ ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ←ȱȱȮȱŗȱȱȱȱȱȱȱȱȦȦȱȱ£ûȱȱǻ Ǽȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱȱȱȱȏ ȱ
ȏȱ
ȏ ȏȏȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ
ãǯȱȱȱȱ ȱǯȱ
ȱ
Programm BP
1:import java.io.*;
2:import java.util.*;
3:public class P01NQueens {
4: private static final String FileOutputName =
5:
"nQueens.out";
6: public static void main(String[] args)
7:
throws IOException{
174
Grundlegende Algorithmen mit Java
8:
PrintStream out =
9:
new PrintStream(new File(FileOutputName));
10:
try {
11:
System.out.print(" n = ");
12:
Scanner sc = new Scanner(System.in);
13:
if (!sc.hasNextInt()) {
14:
return;
15:
}
16:
int n = sc.nextInt();
17:
int noSol = 0;
18:
int[] x = new int[n];
19:
int k = 0;
20:
x[k] = -1;
21:
while (k >= 0) {
22:
boolean flag = false;
23:
while (!flag && x[k] < n - 1) {
24:
x[k]++;
25:
flag = true;
26:
for (int i = 0; i < k; i++)
27:
if ( x[i] == x[k] ||
28:
Math.abs(x[i] - x[k]) == k – i
29:
)
30:
flag = false;
31:
}
32:
if (flag) {
33:
if (k == n - 1) {
34:
for (int i : x) {
35:
out.print(i + 1);
36:
out.print(' ');
37:
}
38:
out.println();
39:
noSol++;
40:
} else
41:
x[++k] = -1;
42:
} else
43:
k--;
44:
}
45:
out.print(n);
46:
out.print(' ');
47:
out.println(noSol);
48:
} finally {
49:
out.close();
50:
}
51: }
52:}ȱ
ȱ
7
Backtracking
175
DZȱȱ ȬȱȱȱŘŗȱ ȱûǰȱȱ ȱȱȱȱ
ûȱȱǻ£ ȱŖȱȱȬŗǼȱǯȱ ȱȱŘřȱȱȱ Ȭȱǰȱȱ
ȱ §ȱ ãȱ ȱ ¡ǽǾȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ¡ǽǾȱ £ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ
§ǯȱȱ
ȱȱȱǮ§ȃȱȱ¡ǽǾȱȱǻȱȬ ȱȱȱřŘȱûȱǼǰȱ
ȱȱ ȱȱ ȱȱȱ£ȱȱǻȱřřǼȱȱȱȱȬ
ȱãǰȱȱ ȱȱȱȱȱȱȱȱ£ȱ§ȱȱȬ
ȱ Śŗȱ £ȱ ȱ ȱ ȱ Ŗǯȱ ȱ ȱ ȱ ȱ ȱ Ǯ§ȃȱ ȱ ȱ
ȱǰȱȱȱ ȱȱȱ£ûȱǻȱŚřǼǯȱ
ȱȱûȱȱȱȱ ǰȱȱȱ£ȱȱȱȱ
ȱ §ǰȱȱ ¡§ȱȱȱȱ¡ǯȱ
ȱ
Allgemeine Bemerkungen zum Backtracking-Verfahren
ȱȱȱ§ȱȱȱǻ ȱȱ ȱ
ȱ ȱ ȱ ǻŗȱ ŗdzŗǼȱ ȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
û£ȱǰȱȱǻŗȱŗdzǼȱ£ȱȱãȱûȱǷǼǰȱȱȱ£ȱ£ȱ
¡ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ
ȱ £ȱ ããȱ ȱ ǻ£ǯǯȱ ȱ ¢ Ǽǯȱ
ûȱȱ ȱȱȱȱãȱȱDZȱ
ȱ
ȱ
• ȱȱûȱȱȱȱãȱãȱǯȱ
• ȱ ãȱ ãȱ ȱ ȱ ȱ §ȱ ǰȱ ȱ ȱ
£ §ȱȱȱȱ£ȱȱȱǯȱ
• ȱãȱȱ ȱȱ DZȱ¡ǽŗǾǰȱ¡ǽŘǾǰȱdz¡ǽǾǯȱ
•
ȱȱȱãȱ ȱǰȱȱȱ£ȱȬȱȱ£ãȱȱ
¡ǽǾȱ£ȱȱãȱûǰȱ ȱȱȱ¡ǽŗǾǰȱ¡ǽŘǾǰȱdz¡ǽȬŗǾȱȱ
ȱ ǯȱ
• ȱãȱǰȱȱ ȱȱãȱȱȱȱǯȱ
ȱ
ȱ
§ȱȱã¢ȱȱȱȬȱȱȱ ȱȬ
ȱ DZȱ ȱ ȱ ȱ ȱ §ȱ ǻȬȬǼǰȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ãȱ ǻȱ ȱ ȱ ûȱ Ǽǰȱ Ȭ
ȱ ȱ ȱ ȱ ǻȱ ûȱ ȱ ȱ ȱ ȱ ǰȱ ¢ǰȱ
ǰȱȱǼǯȱȱ
ȱ
176
Grundlegende Algorithmen mit Java
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ǯȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ¡ǽǾȱ ȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ dzǰȱ ȱ
ȱãǯȱȱ
ȱ
ȱȱȱ£ȱ DZȱ
ȱ
ȱ
ȏȏ ȱ
ȱ
ȱ←ȱŗȱ
ȱ
ȱǻ≥ŗǼȱȱ
ȱ
ȱȱȱ ȱǻȱ∃ǻȱȱȱ ȱûȱ¡ǽǾǼȱǼȱȱ
ȱ
ȱȱȱȱȱȱ¡ǽǾȱ←ȱȱȱȱ ȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱûȱȱȬȱȱ
ȱ
ȱȱȱȱȱȱ ȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾȱȱãǼȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱ←ȱƸŗȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȦȦȱȱ §ȱ
ȱ
ȱȱȱȱȱ←ȱȬŗȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȦȦȱȱû §
ȱ
ȏȱ
ȱ
ȏ ȏȏ ȱ
ȱ
ȱ
ȱȬȱãȱȱȱȱ ǰȱ£ǯȱǯȱȱȬ
ȱDZȱ
ȱ
ȱ
ȏȏǻǼȱȱ
ȱ
ȱȱȱȱǻȱãȱȱȱ¡ǽǾǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱȱ ȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾȱ£ȱȱãȱûȱǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱ ȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾȱȱãȱǼȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱ ȏȏǻƸŗǼȱ
ȱ
ȱȱȱȱȏȱ
ȱ
ȏ ȏȏǻǼȱȱ
ȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãǰȱ ȱ ûȱ ȱ Ȭ
ȏȏǻŗǼȱǯȱ
ȱ
Aufgaben
ŗǯ
ȱ ȱ ȱ ã¢ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ
ȱȱǯȱ
7
Backtracking
Řǯ
řǯ
177
ȱȱȱȱȱǰȱȱȱ ȱǯǯȱȱȱȬ
£ȱȱ ǰȱȱȱȱȱȱ¢ȱǽǾȱ Ȭ
ȱ ǯȱȱȱȱȱȱǵȱ
ȱȱȱȱǰȱȱȱȱȱãǯȱȱûȱȱ
ȱDZȱ
ȱ
void back(List<Integer> x, int n, PrintStream out){
int i, xk, k=x.size();
boolean flag;
for(xk=0; xk<n; xk++){
flag = true;
if(x.size()==k+1) x.remove(x.size()-1);
for(i=0; flag && i<k; i++)
if(x.get(i)==xk || Math.abs(xk-x.get(i))==k-i)
flag=false;
if(flag){
x.add(xk);
if(k==n-1) writeSolution(x, out);
else back(x, n, out);
}
}
}
ȱ
Śǯ
ȱȱȱȱ£ȱǰȱȱȱȱȱȱȱȱ
ȱȱǯȱȱ£ȱȱȱ DZȱȱ
if(x.size()==k+1) x.remove(x.size()-1); ǵ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ
ȱȬȱȱ£ȱǰȱȱȱûȱȱŗǰȱŘǰȱdzǰȱŘȱȬ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
Ȭȱȱȱȱǯȱȱȱȱȱȱȱ
ȱȱȱȱŚDZȱ
§16 3 2 13 ·
¸
¨
¨ 5 10 11 8 ¸ ȱ
A=¨
9 6 7 12 ¸
¸
¨
¨ 4 15 14 1 ¸
¹
©
ȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱ ȱ ȱ
n(n 2 + 1)
ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
2
ȱ ȱ ȱ ȱ Śȱ ȱ ȱ ȱ ǯȱ ǯȱ
ȱȱȱȱǰȱȱûǰȱȱȱȱ×Ȭ¡ȱȱŚȱ
≤ȱȱ≤ȱśŖȱȱȱȱǯȱ
178
Grundlegende Algorithmen mit Java
Problem 2. Das Problem der n Türme
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ×ȱ ǯȱ ȱ
ȱȱãǰȱ ȱȱȱûȱȱȱǰȱȱȱȱȱȬ
ȱ ȱ ǻŘȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱȱȱȱȱǼǯȱȱȱȱǰȱȱŚȱ≤ȱȱ≤ȱŘŖȱǯȱ
DZȱtȱȱȱ ȱȱȱȱȱȱȱǯȱ DZȱ ȱȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ
ȱȱȱȱȱ£ȱȱãǰȱȱȱȱȱȱ£ȱǯȱ
DZȱ
ȱ
Tastatur
nTowers.out
n = 5
1 2 3 4 5
1 2 3 5 4
…
5 4 3 1 2
5 4 3 2 1
5 120
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȬȬȱ ȱ §ǯȱ ȱ ǰȱ ȱ £ ȱ
ûȱ ȱ ȱ ȱ ǰȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱûǯȱȱǰȱȱȱãȱûȱȱȬȬȱ
ȱ ȱ ãȱ ûȱ ȱ ȱ ǯȱ ȱ §ȱ ȱ ãȱ ûȱ
ȱ ȱ ȱ ȱ ¢ȱ ¡ǽǾǰȱ ȱ ȱ ǯȱ ȱ ȱ
ȱ §ȱ ǻȱ ȱ ȱ ȱ Ǽȱ §ȱ ȱ £ȱ ȱ
ãǯȱȱ£ȱ ȱȱȱȱȱûȱȱãȱ
¡ǽǾǰȱ ȱ ¡ǽŖǾǰȱ ¡ǽŗǾǰȱ dzǰȱ ¡ǽȬŗǾȱ ȱ DZȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ £ȱ ûǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ŚȬśȱ
ȱȱȱûȱȱȱȱȱ£ȱđȱȱȱŘŝȬ
řŗȱDZȱ
ȱ
27-31:
if(x[i]==x[k]) flag=false;
ȱ
ǻ ȱȱȱȱȱȱȱ ȱȱȱȱǰȱǰȱȱȱȱ
ȱ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾȱȱ ȱûȱȱãȱǷǼǯȱȱ
ȱ
DZȱȱȱȱȱȱȱȱȱ ȱȱǰȱȱ
ȱȱ£ȱȱãȱǷǯȱ
ȱ
7
Backtracking
179
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱ ǯȱ
ȱ ȱ ȱ ¡ȱ ǯȱ ȱ ȱ ȱ ȱ
ǰȱȱȱ¡ȱȱ ǯȱ
Problem 3. Das Problem der Türme auf den ersten m Reihen
ȱȱȱãǰȱȱ¡ȱ£ȱȱûȱȱȱȱȬ
ȱȱȱȱȱȱȱȱ£ȱ£ǰȱȱȱȱ
ȱȱȱȱȱǻŚȱ≤ȱȱ≤ȱŘŖǰȱŗȱ≤ȱȱ≤ȱȱǼǯȱDZȱȱȱȱȱȱȱ
ȱ ȱ ȱ ǯȱ DZȱ ȱ ãȱ ȱ ȱ ȱ ȱ ǯȱ Ȭ
ȱȱȱȱ£ȱȱǰȱȱȱȱ£ȱȱãǰȱ ȱȱDZȱ
ȱ
Tastatur
nmTowers.out
n = 6
1 2 3 4
m = 4
1 2 3 5
…
6 5 4 2
6 5 4 3
6 4 360
ȱ
Problemanalyse und Entwurf der Lösung
ȱ¡ȱ£ȱȱûȱȱȱȱȱȱǯȱȱ Ȭ
ȱûȱȱȱȱȱŘȱȱǰȱȱȱȱȱȱ
ȱ ȱ ûȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱǰȱ££ȱȱȱȱȱ£ȱ£ ǯȱ§ȱȱ
ȱȱDZȱ
ȱ
27-31:
if(x[i]==x[k]) flag=false;
ǻȱȬûȱǼȱ
33:
if(k==m-1){
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻãȱǰȱ ȱȱȱȱǼǯȱ
ȱ
DZȱȱȱȱȱȱ£ȱȱȱȱûȱǯȱȱ£ȱ
ȱãȱȱȱ
n!
= n(n − 1)(n − 2)...(n − m + 1). ȱ
(n − m)!
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱǯȱ
ȱ ȱ ȱ ¡ȱ ǯȱ ȱ ȱ ȱ Ȭ
ȱǰȱȱȱ¡ȱȱ ǯȱ
180
Grundlegende Algorithmen mit Java
Problem 4. Das Problem der aufsteigenden Türme auf den ersten
m Reihen
ȱȱȱãǰȱȱ¡ȱ£ȱȱȱûȱȱ
ȱ ×Ȭȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ £ǰȱ ȱ ȱ ȱ ȱ
ȱȱǻŚȱ≤ȱȱ≤ȱŘŖǰȱŗȱ≤ȱȱ≤ȱȱǼǯȱDZȱȱȱȱȱȱȱûȱ
ǯȱ DZȱ ȱ ãȱ ȱ ȱ ȱ ȱ ǯȱ ǰȱ
ȱȱȱ£ȱȱȱȱǰȱȱȱȱ£ȱȱãȱǰȱȱȬ
DZȱ
ȱ
Tastatur
nmATowers.out
n = 6
1 2 3 4
m = 4
1 2 3 5
…
2 4 5 6
3 4 5 6
6 4 15
ȱ
ǯȱ ȱ ȱ ȱ ȱ £ȱ ȱ ûȱ ¡ǽŗǾǰȱ ¡ǽŘǾdzȱ ¡ǽǾȱ ȱ ǰȱ
ȱûȱȱǰȱȱ∈ȱǿŗǰȱŘǰȱdzǰȱȀǰȱȱȱǀȱǰȱDZȱ¡ǽǾȱǀȱ¡ǽǾǯȱDZȱûȱƽŞȱȱƽśȱȱ
£ ȱãDZȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱ£ȱȱȱǰȱȱȱȱȱȱȬ
ȱ ȱǯȱȱȱ£ ȱãǰȱ ȱȱȱȱǯȱȱȱ
ȱȱȱ¡ǽƸƸǾȱȱȱȱȱȱŚŗȱȱ¡ǽȬŗǾǯȱȱȱ£ ȱ
ãȱȱȱûȱȱǁȱŗȱȱ¡ǽȬŗǾȱǀȱ¡ǽǾǯȱȱȱ ȱȱȱȱ
ȱȱȱtǯȱȱ
ȱ
7
Backtracking
181
DZȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ǯȱ ȱ
£ȱȱãȱȱȱ
n!
n(n − 1)(n − 2)...(n − m + 1)
=
.ȱ
m!(n − m)!
m!
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱ ǯȱ
ȱȱ¡ȱ£ȱȱ ȱȱȱȱȬ
¡ǯȱ
Problem 5. Die Freundschafts-Jugendherberge
ȱ ȱ Ȭ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ
ȱȱȱ£ȱȱȱ ȱȱȱǯȱȱ£ ȱȱ
ȱ ȱ ȱ £ǰȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ £ ȱ Ȭ
ȱ£ȱãǯȱȱȱǰȱȱȱȱȱȱȱŗǰȱŘǰȱdzǰȱȱȬ
ȱ ǯȱDZȱȱȱȱûȱȱȱǯȱDZȱȱ£ãȱ
ȱȱǯȱǰȱȱȱǯȱȱ£ȱȱȱȱȱȱȬ
£ȱȱãȱǯȱDZȱ
ȱ
Tastatur
friends.out
n=5
1 3 5 2 4
…
3 5 2 4 1
…
5 3 1 4 2
5 10
ȱ
Problemanalyse und Entwurf der Lösung
đȱȱǰȱȱȱȱȱȱ¡ǽǾȱȱȱûǰȱȱ
ȱȱ£ȱûǰȱȱȱ£ȱ£ ȱȱȱȱŗȱȱȬ
ȱ ǯȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ Ȭŗȱ ȱ ǻŗȱ ȱ ȱ ȱ ȱ ȱ
Ǽǯȱ ȱȱȱ ȱȱȱȱŘŜȬřŖȱ£ȱDZȱ
ȱ
if(k==n-1&&(abs(x[k]-x[0])==1||Math.abs(x[k]-x[0])==n-1))
flag=false;
if(k>0&&(abs(x[k]-x[k-1])==1||Math.abs(x[k]-x[k-1])==n-1))
flag=false;
for(i=0; i<k; i++) if(x[i]==x[k]) flag=false;
ȱ
182
Grundlegende Algorithmen mit Java
Aufgaben
ŗǯ
Řǯ
ãȱȱȱȱȱǯȱ
ȱȱȱȱȱ§ȱȱûȱȱ£ȱȱãǯȱ
Problem 6. Partitionen einer natürlichen Zahl
ȱûȱȱ§ȱȱȱȱûȱȱǯȱûȱȱȬ
ȱ ãđȱ ŗȱ ȱ ȱ ȱ ȱ ãǯȱ ȱ ȱ ȱ ǰȱ ȱ
ȱȱȱȱûȱȱȱǻŗ≤ȱȱ≤ȱŝśǼǰȱȱȱȱ
£ȱȱãǯȱDZȱ
ȱ
Tastatur
nPart.out
5
1 + 1 + 1 + 1 + 1
1 + 1 + 1 + 2
1 + 1 + 3
1 + 2 + 2
1 + 4
2 + 3
5
Anzahl der Loesungen = 7
50
…
24 + 26
25 + 25
50
Anzahl der Loesungen = 204226
75
…
36 + 39
37 + 38
75
Anzahl der Loesungen = 8118264
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱǰȱȱȱãȱȱȱȱ¢ȱ¡ǽŗǾǰȱ¡ǽŘǾǰdzǰȱ¡ǽǾȱȱȱ
ȱȱ ȱDZȱ
• ȱȱȱȱȱǯȱ
• ȱȱȱǯȱ
ȱ£ȱ¡ǽŗǾǰȱ¡ǽŘǾǰȱdzǰȱ¡ǽǾȱȱȱ ȱûȱȱãȱǻãȱ£ȱȱãȬ
ȱ ûǼǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱȱ¡ǽǾȱ£ȱǰȱȱ ȱ¡ǽǾȱȱ¡ǽȬŗǾȬŗȱȱ ȱȱ
ȱ ǽǾǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ¡ǽǾȱ ǯȱ ȱ
ǽǾƽȱǰȱȱ ȱȱãǯȱ
ȱ
7
Backtracking
Programm
import java.io.*;
import java.util.*;
public class P06NPart {
private static final String FileOutputName = "nPart.out";
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(System.in);
int n = sc.nextInt();
int noSol = 0;
int x[] = new int[n + 1];
int s[] = new int[n + 1];
boolean isSuccessor, isCandidate = false;
int k = 1;
while (k > 0) {
do {
if (x[k] < n) {
isSuccessor = true;
x[k]++;
s[k] = s[k - 1] + x[k];
isCandidate = s[k] <= n;
} else
isSuccessor = false;
} while (isSuccessor && !isCandidate);
if (isSuccessor)
if (s[k] == n) {
out.print(x[1]);
for (int i = 2; i <= k; i++) {
out.print(" + ");
out.print(x[i]);
}
out.println();
noSol++;
} else {
++k;
x[k] = x[k - 1] - 1;
}
else
k--;
}
out.print(" Anzahl der Loesungen = ");
out.print(noSol);
183
184
Grundlegende Algorithmen mit Java
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ¡Ȭ
ȱȱȱ ǯȱ
n.in
nPart.out
5
5
2 + 3
1 + 4
1 + 2 + 2
1 + 1 + 3
1 + 1 + 1 + 2
1 + 1 + 1 + 1 + 1
Anzahl der Loesungen = 7
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ûȱ ¡ǽǾȱ ȱ ȱ ȱ ȱ ȱ ȬȬȱ ǻȱ ŗǼȱ
ȱ ǻȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǿdzȀ ȱ ȱ ȱ ǿȀȱ
ȱǯǼǯȱ
ȱȱȱȱǯȱ
ȱ£ȱȱȱȱȱȱȱȱȱȱ£ȱȱ
ȱ ȱ ȱ ȱ ǯȱ £ȱ ȱ ȱ ȱ
ȱȱǯȱȱûȱƽśDZȱ
ȱ
Partitionen
Anzahl unterschiedlicher Zahlen
1
1 + 1 + 1 + 1 + 1
2
1 + 1 + 1 + 2
2
1 + 1 + 3
2
1 + 2 + 2
2
1 + 4
2
2 + 3
1
5
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ DZȱȱȱȱȱȱŗŘȱ
7
Backtracking
185
ȱ£ȱȱȱȱȱȱȱȱŗŘǯȱȱȱȱȬ
ǰȱȱȱ£ȱûȱŗȱ≤ȱȱ≤ȱŚŖȱǯȱ ȱ ȱȱȱȱȬ
ǯȱ£ȱȱȱDZȱ
parti.out
2 2 2 OK
…
5 12 12 OK
…
27 11732 11732 OK
28 14742 14742 OK
…
40 177970 177970 OK
Problem 7. Erdkunde-Referate
ȱ Ȭȱ ãǰȱ ȱ ȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ
ǯȱȱȱûȱȱȱûȱȱȱǰȱǻȱ≤ȱǼȱȱȱȱȬ
ȱȱȱ ȱǯȱ ȱȱȱǰȱȱȱȱ
ȱȱȱȱȱȱȱûȱǰȱ ȱȱȱȱȱ
ǯȱ DZȱtȱȱȱȱȱȱȱȱȱȱǯȱDZȱȱ
ȱȱȱȱǯȱȱãȱȱȱȱȱ£ȱȱ
ãǯȱDZȱ
ȱ
Tastatur
referat.out
n=3
1 1 2
m=2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
Anzahl der Loesungen = 6
ȱ
Problemanalyse und Entwurf der Lösung
ǯȱ ȱ ȱ DZȱ →ȱ đȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǻ¡Ǽȱûȱȱ¡ȱzȱȱȱǻ∀¢ȱ∈ȱ∃¡ȱ∈DZȱǻ¡Ǽƽ¢Ǽǯȱ
ȱ
ȱȱȱ£ȱãǰȱȱ ȱȱȱȱȱȱȬ
ȱƽǿŗǰȱŘǰȱdzǰȱȀȱȱȱȱƽǿŗǰȱŘǰȱdzǰȱȀȱǯȱȱȬ
¢ȱȱȱȱȱȱȱ§ǯȱȱ£ȱȱȱ¡ǽǾǰȱ
ȱ ȱ ãȱ £ǰȱ ȱ ûȱ ¡ǽǾȱ ȱ ȱ ȱ ãȱ ȱ ȱ
ûȱǰȱȱ¡ǽŖǾǰȱ¡ǽŗǾǰȱdzǰȱ¡ǽǾȱȱȱãȱǯȱđȱȬ
£ȱ ȱ ȱ ȱ ǽǾȱ ǰȱ ȱ ǽǾȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
186
Grundlegende Algorithmen mit Java
ȱȱ¡ǽŖǾǰȱdzǰȱ¡ǽǾȱ ȱ ǯȱ ȱȱ ȬǰȱȱȱȱȱȬ
ȱȱûȱ¡ǽǾȱǰȱ ȱ DZȱȱ
•
ȱ ȱ ȱ ȱ ȱ ûȱ ¡ǽǾȱ ȱ ȱ ǻif(x[k]>=0)…Ǽȱ ȱ
£ȱȱȱ¡ǽǾȱȱ¢ȱǽǾȱȱǻvMark[x[k]]--ǼDzȱ
• ȱ ȱ §ȱ Ȭ ȱ ȱ £ȱ ȱ ȱ ȱ
£§ǰȱȱȱȱ¡ǽŖǾǰȱ¡ǽŗǾǰȱdzǰȱ¡ǽǾȱDzȱ
•
ȱȱ£ȱȱȱȱ£ȱȱȱûȱȱǻȬ
ŗȬǼȱȱȱȱȱȱȱȱȱȱ£ǰȱȱ ȱãȱȱ
ãȱȱ¡ǽŖǾǰȱ¡ǽŗǾǰȱǯǯǯǰȱ¡ǽǾȱȱȱȱǯȱ
ȱ
DZȱȱ£ȱȱȱȱ ȱȱȱ ƽǿŗǰȱ
ŘǰȱdzǰȱȀȱȱȱȱƽǿŗǰȱŘǰȱdzǰȱȀȱȱȱȱȱȱDZȱ
ȱ
S j ( n, m ) =
m −1
i § m·
§ m·
¦ (−1) ¨¨© i ¸¸¹(m − i) = m − ¨¨© 1 ¸¸¹ ⋅ (m − 1) + ... + (−1)
n
n
n
m −1
⋅ m ȱȱȱȱȱȱȱȱȱȱȱȱȱ
ǻŗǼȱ
i =0
ȱ ȱ ȱ £ȱ ȱ ãȱ ȱ ȱ ȱ ȱ
ãȱȱȱȱȱȱȱȱ ǯȱ
ȱ
§ǰȱ ȱ
Programm
import java.io.*;
import java.util.*;
public class P07Referat {
private static final String FileOutputName = "referat.out";
public static void main(String[] args) throws IOException {
PrintStream out = new PrintStream(
new File(FileOutputName));
try {
Scanner sc = new Scanner(System.in);
System.out.print(" n = ");
int n = sc.nextInt();
System.out.print(" m = ");
int m = sc.nextInt();
int x[] = new int[n];
int xIdx = 0;
int vMark[] = new int[n];
x[0] = -1;
int noSol = 0;
while (xIdx >= 0) {
int k = xIdx;
boolean flag = false;
while (!flag && x[k] < m - 1) {
7
Backtracking
187
if (x[k] >= 0)
vMark[x[k]]--;
vMark[++x[k]]++;
flag = true;
int noMarked = 0;
for (int i = 0; i <= k; i++)
if (vMark[i] != 0)
noMarked++;
if (noMarked + n - 1 - k < m)
flag = false;
}
if (flag) {
if (k == n - 1) {
for (int i : x) {
out.print(i + 1);
out.print(' ');
}
out.println();
noSol++;
} else
x[++xIdx] = -1;
} else {
if (x[k] >= 0)
vMark[x[k]]--;
xIdx--;
}
ȱ ȱ ȱ ǮforeachȬȃǰȱ
ȱ ȱ ȱ ȱ śȱ ûȱ ǰȱ Ȭ
ȱ ȱ ȱ ȱ ȱ
ȱǮforȃDZȱ
for (int i : x)ȱ
ȱDZȱ
for(type iterVar:iterableObj)
Anweisung;
}
out.print("Anzahl der Loesungen =
out.print(noSol);
} finally {
out.close();
}
");
}
}ȱ
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱȱȱȱȱǰȱȱȱãȱȱ¡ȱ
ȱȱ ǯȱ
ȱȱȱǰȱ ȱȱȱûȱȱȱŜȱȱ ȱûȱ¡ǽǾȱ
ȱ ȱ ǻȱ ȱ ȱ ȱ ȱ ȱ Ǽǰȱ ȱ
ȱȱȱȱȱȱǯȱ
ȱȱȱȱȱȱǯȱ
ǮforeachȬȃǰȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ǰȱ ȱ
£ȱȱȱȱȱȱȱ¡£ȱ
188
Grundlegende Algorithmen mit Java
śǯ
ȱ ȱ ȱ ȱ ȱ §ǯȱ ȱ ȱ ȱ Ȭ Ȭ
ȱ ûȱ ȱ ȱ ȱ ǮforeachȬȃȱ ȱ ȱ
ȱȱȱǰȱȱȱȱȱȱûȱȱ
¢ȱ£ǯȱ
ȱ ȱ ȱ ȱ ǻŗǼǰȱ ȱ ȱ §ȱ ǯȱ ȱ
ȱȱȱȱûȱȱȱȱ£ȱȱȱȬ
ȱ£ ȱȱȱ ƽǿŗǰȱŘǰȱdzǰȱȀȱȱȱȱ
ƽǿŗǰȱŘǰȱdzǰȱȀǯȱȱȱȱǰȱȱȱ£ȱǯȱȬ
DZȱ
nm.in
noSurj.out
3 2
6
7 4
8400
Problem 8. Alle Wege des Springers
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ś×śȬǰȱ ȱ ȱ ȱ Ȭ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭȱ
ȱûȱȱȱǯȱ ȱãȱ
ǻȱ Ǽȱ ȱ ȱ ¡ǰȱ ȱ ȱ Ȭ
ȱ ¢ǰȱ ȱ ȱ ȱ ǯȱ Ȭ
ǯȱ ȱȱ£ȱ ȱȱ
ŗȱȱȱûȱȱȱ ȱȱŘȱȱŘśȱ
£§ǰȱȱǯȱȱȱǮȱǷȃǰȱ ȱȱȱãȱǯȱ
ȱ
Tastatur
springer.out
4 2
Loesung: 1
19
14
3
8
25
2
9
18
13
4
15
20
5
24
7
10
1
22
17
12
21
16
11
6
23
…
Loesung: 56
23
12
7
4
21
6
17
22
13
8
11
24
5
20
3
16
1
18
9
14
25
10
15
2
19
ȱ
ȱ
ȱ
7
Backtracking
189
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱǯȱȱȱȱȱȱȱȱãȱ
ȱãȱȱȱȱǯȱ
ȱǻ¡ǰȱ¢Ǽȱȱ ȱȱȱǰȱȱãȬ
ȱȱȱȱDZȱǻ¡ȬŘǰȱ¢ȬŗǼǰȱǻ¡ȬŘǰȱ¢ƸŗǼǰȱ
ǻ¡Ȭŗǰȱ ¢ȬŘǼǰȱ ǻ¡Ȭŗǰȱ ¢ƸŘǼǰȱ ǻ¡Ƹŗǰȱ ¢ȬŘǼǰȱ ǻ¡Ƹŗǰȱ ¢ƸŘǼǰȱ ǻ¡ƸŘǰȱ ¢ȬŗǼǰȱ ǻ¡ƸŘǰȱ
¢ƸŗǼǯȱȱȱȱȱ ȱȱȱ
Ŗȱ ǰȱ ȱ ȱ £ȱ ȱ ȱ ȱ ŗǯȱ ȱ
ȱ ȱ ȱ ȱ Ȭȱ ǻǼǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
ȱȱǯȱȱ ȱ ȱǰȱȱ ȱȱǻ¡ ǰȱ¢ Ǽȱ ȱ
ûȱȱãȱǰȱȱ ȱûǰȱȱ ȱȱ ȱȱȱȱ ȱ
ȱȱȱȱȱŖȱȱǻȱȱ ȱȱȱǼǯȱȱȱȱȱ
ȱ£ȱ ǰȱȱ ȱǻ ǰȱ ǰȱƸŗǼȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P08Springer {
private static final String FileOutputName = "springer.out";
private int nSol;
private int[][] table;
private PrintStream out;
private int n;
public P08Springer(int n, PrintStream out) {
this.n = n;
this.table = new int[n][n];
this.out = out;
}
private void writeSolution() {
out.print(" Loesung: ");
out.println(++nSol);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
out.printf("%3d ", table[i][j]);
out.println();
}
190
Grundlegende Algorithmen mit Java
}
void run(int l, int c) {
this.nSol = 0;
this.table[l - 1][c - 1] = 1;
this.back(l - 1, c - 1, 1);
}
private void back(int l, int c, int step) {
if (n * n == step) {
writeSolution();
return;
}
int dx, dy, lnew, cnew;
for (dx = -2; dx < 3; dx++)
for (dy = -2; dy < 3; dy++)
if (Math.abs(dx * dy) == 2) {
lnew = l + dx;
cnew = c + dy;
if (0 <= lnew && lnew < n && 0 <= cnew && cnew < n
&& table[lnew][cnew] == 0) {
table[lnew][cnew] = step + 1;
back(l + dx, c + dy, step + 1);
table[lnew][cnew] = 0;
}
}
}
public static void main(String[] args) throws IOException {
PrintStream out = new PrintStream(
new File(FileOutputName));
try {
Scanner sc = new Scanner(System.in);
int l = sc.nextInt();
int c = sc.nextInt();
new P08Springer(5, out).run(l, c);
} finally {
out.close();
}
}
}
Aufgaben
ŗǯ
Řǯ
£ȱȱȱȱǰȱȱȱȱ £ȱǯȱ
ȱȱȱȱȱȱûȱȱǯȱ
7
Backtracking
řǯ
191
ȱȱȱǰȱȱȱȱȱȱûȱȱȱȱ
ǯȱȱȱȱȱȱǰȱȱȱȱȱȱȱȬ
ȱǰȱ ȱȱȱȱȱǯȱ
Problem 9. Das Fotoproblem
ȱ £ đȱȱȱȱȱ¡ȱȱȱȱȱǯȱȱ§Ȭ
ȱ ȱ ǯȱ ȱ ȱ ȱ £ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ
ûǰȱȱ ȱȱǯȱȱ£ȱȱȱȱȱǰȱȱ
ȱ ȱ §ȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ DZȱ Řǰȱ řǰȱ dzǰȱ Ƹŗǯȱ ȱ ȱ ȱ ȱ ¡ȱ ãȱ ȱ
£ȱȱǰȱ ȱȱȱȱȱȱȱȱǯȱDZȱ
ȱȱȱǯȱȱȱȱȱȱȱ£ȱȱȱȱȱȱ
¡ȱǻ¡ȱŗŖŖǼȱȱȱȱȱȱ§ȱ¡ǯȱDZȱȱȱȱ
ȱȱǯȱ£ȱȱ£ȱȱȱ ǰȱȱȱȱȱǰȱȬ
ȱȱ§ȱǰȱȱȱȱȱȱȱŘǰȱřǰȱdzǰȱȱƸŗȱǰȱ
ȱȱDZȱ
ȱ
foto.in
foto.out
3
4 5
2 2 0 3 3
1 1 0 1 1
0 0 0 3 0
0 0 0 1 0
4 4 0 3 3
1 1 0 1 1
4 0 3 3 0
1 0 1 1 0
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ǻǼȱ ǰȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱȱȱȱȱȱǯȱ ȱȱȱ
§ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱȱȱǯȱȱ
Programm
import java.io.*;
import java.util.*;
public class P09PhotoProblem {
private static final String FileInputName = "foto.in";
private static final String FileOutputName = "foto.out";
private int m, n;
private int[][] a;
192
Grundlegende Algorithmen mit Java
P09PhotoProblem(int[][] a, int m, int n) {
this.a = a;
this.m = m;
this.n = n;
}
private void color(int i, int j, int col) {
if (0 <= i && i < m && 0 <= j && j < n && 1 == a[i][j]) {
a[i][j] = col;
color(i, j - 1, col);
color(i, j + 1, col);
color(i - 1, j, col);
color(i + 1, j, col);
}
}
void run(PrintStream out) {
int col = 1;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (1 == a[i][j])
color(i, j, ++col);
out.println(col);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
out.print(a[i][j]);
out.print(' ');
}
out.println();
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
int m = sc.nextInt();
int n = sc.nextInt();
int[][] a = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
a[i][j] = sc.nextInt();
}
}
new P09PhotoProblem(a, m, n).run(out);
7
Backtracking
193
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ
ǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ £ ȱ ȱ £ȱ ȱ ȱ ãǰȱ
ȱȱȱȱȱȱȱǻȱȱȱȱ¡ȱ
ȱȱǼǯȱûȱȱȱȱȱǯȱ
Problem 10. Der ausbrechende Ball
ȱȱȱ×Ȭ¡ȱȱȱȱȱȱ
ǰȱ ȱ ȱ ãȱ ǻȱ Ǽȱ ȱ Ȭ
ǯȱ ȱ£ȱ ȱȱǰȱȱȱȱȱȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ȱ ã ȱ ǰȱ ȱ Ǯȃȱ ȱ ȱ ȱ Ȭ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ǰȱ ûȱ ȱ ǯȱ ȱ ȱ ȱ ãȱ ǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ Ǯ ȃȱ ȱ §đȱ
ȱȱȱȱ¡ȱǰȱȱȱȱǯȱȱȱȱǰȱȱ
ȱ ã ȱȱ¡ȱȱ §ȱǰȱȱȱ ȱȱȱãȱ
ǯȱDZȱ ȱȱȱǯȱȱȱȱȱȱȱȱȱȱȱȱǻŚȱ
≤ȱǰȱȱ≤ȱŘŖǼǰȱȱȱ§ȱȱȱȱ¡ȱȱȱ ãȱȱȱȱ
£ȱȱȱ ȱȱǯȱDZȱ ȱȱ§ȱȱãȬ
ȱȱȱȱ£ȱǮ £ȃȱȱ¡ǯȱDZȱ
ȱ
ball.in
ball.out
4 4
(3, 2) (2, 2) (1, 2)
1 1 0 1
(3, 2) (2, 2) (2, 3) (1, 3)
3 2 1 3
(3, 2) (3, 1)
4 5 2 3
(3, 2) (3, 3) (2, 3) (1, 3)
3 6 1 0
(3, 2) (3, 3) (4, 3)
3 2
ȱ
194
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱ ãȱ ȱ ȱȱȱǯȱ ȱ ȱȱ ȱȱ
ȱ £ȱ ȱ DZȱ ûȱ ȱ ȱ ǻǰȱ Ǽȱ ȱ Ŗȱ ≤ȱ ȱ ǀȱ ǰȱ Ŗȱ ≤ȱ ȱ ǀȱ ȱ ȱ ¡ȱ
£ȱ ȱ ȱ ȱ ȱ ←ȱ ȘƸǯȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
£ȱ ȱ ȱ ȱ DZȱ ȱ ←ȱ ȱ ȱ ǰȱ ȱ ←ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱ ȱȱȱȱ¡ȱȱ£ȱǯȱȱȱȱ
ȱǻǼȱǻȱǰȱȱȱȱȱ¡ȱȱȱ§đȱȱ
ȱ Ȧȱ ȱ ȱ Ǽǰȱ ȱ ǻǼȱ ǻȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ
Ǽǯȱ ȱ ãȱ ȱ ȱ ȱ ȱ ǻǼȱ ǰȱ ȱ ȱ ȱ
ǯȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ
ȱ ȱ ȱ ¡ǽǾȱ ȱ đȱ ǯȱ ȱ ȱ ȱ ȱ ȱ £ȱ
ȱǰȱȱ ȱǻǼȱûȱȱȱȱȱ ãȱȱȬ
ǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P10Ball {
private static final String FileInputName = "ball.in";
private static final String FileOutputName = "ball.out";
private static boolean onTheBorder(int k, int m, int n) {
int l = k / n;
int c = k % n;
boolean flag = false;
if (0 == l || m - 1 == l)
flag = true;
if (0 == c || n - 1 == c)
flag = true;
return flag;
}
private static boolean onTheTable(int line, int col,
int m, int n) {
return (0 <= line && line < m) && (0 <= col && col < n);
}
private static void writeSolution(List<Integer> x,
int T[][], int n,
PrintStream out) {
for (int i = 0; i < x.size(); i++) {
out.print('(');
out.print(x.get(i) / n + 1);
7
Backtracking
out.print(", ");
out.print(x.get(i) % n + 1);
out.print(") ");
}
out.println();
}
private static void back(List<Integer> x,
int T[][], int m, int n,
PrintStream out)
{
int k = x.size() - 1;
int xk = x.get(k);
if (onTheBorder(xk, m, n)) {
writeSolution(x, T, n, out);
return;
}
int l = xk / n;
int c = xk % n;
int lnew, cnew, dx, dy;
for (dx = -1; dx < 2; dx++)
for (dy = -1; dy < 2; dy++)
if (1 == Math.abs(dx + dy)) {
lnew = l + dx;
cnew = c + dy;
if ( onTheTable(lnew, cnew, m, n) &&
T[lnew][cnew]< T[l][c]) {
x.add(lnew * n + cnew);
back(x, T, m, n, out);
x.remove(x.size() - 1);
}
}
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
int m = sc.nextInt();
int n = sc.nextInt();
int[][] t = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
t[i][j] = sc.nextInt();
}
195
196
Grundlegende Algorithmen mit Java
}
int l0 = sc.nextInt() - 1;
int c0 = sc.nextInt() - 1;
List<Integer> x = new ArrayList<Integer>();
x.add(l0 * n + c0);
back(x, t, m, n, out);
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ ȱ ãȱ ȱ ȱ
ȱȱ ȱȱȱȱȱȱȱǯȱ
ȱȱȱȱȱûȱȱǯȱ
Problem 11. Orangensport
ȱ ȱ ȱ ȱ £§ȱ ȱ ǰȱ
ȱȱ ȱȱȱǯȱȱȱ
ȱ ŗŖŖȱ ȱ ȱ ȱ ȱ ȱ ȱ ŗȱ
ȱ ŗŖŖǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ đȱ
ǰȱ ȱ £ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ
£ȱȱȱ ȱȱȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ
ǯȱ ȱ ŗȱ ȱ ȱ
£ȱ ȱ ȱ ȱ £ȱ ǰȱ
ǯǯȱ ȱ ȱ ȱ ȱ £ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ãǯȱ ȱ ȱ ȱ ȱ ȱ ŗȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱȱȱŗȱDzȱ ȱȱȱ ãđȱȱŗȱǰȱȱȱȱȱ
ȱ ȱ Ƿȱ ȱ Řřȱ ȱ ãȱ ȱ ȱ ȱ ȱ ûȱ ȱ
ȱǻ Ǽȱǰȱȱȱȱȱȱǯȱȱ
ǰȱȱȱȱȱȱȱûǯȱȱ§ȱ ȱȱǰȱ
ȱ ȱ ãđȱ ȱ ǯȱ §ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱãǯȱȱȱȱǰȱȱȱ£ȱ ȱǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûǯȱ ȱ ȱ ȱ
7
Backtracking
197
ãȱ §ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱǰȱȱȱȱȱȱȱ ȱȱȱȱȱ
ǰȱ ȱȱȱǻȱȱǼȱȱȱȱǿŗǰȱŘǰȱǯǯǯǰȱŗŖŖȀȱȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ ȱ
ȱ ǰȱ ȱ ȱ ȱãǰȱȱȱȱȱȱǯȱ
ȱûȱȱȱǰȱ ȱȱȱȱǰȱȱđȱȱ
ȱȱȱ ȱǰȱȱ ȱȱȱȱȱ§ȱ
ȱ ȱãǯȱȱȱȱȱãđȱȱ ȱȱǰȱ
ȱ ȱ ȱ ȱ ȱ ûȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǿŗǰȱ Řǰȱ ȱ ǯǯǯǰȱ ŗŖŖȀȱ £ȱ §ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱȱȱ ȱȱȱ ǰȱ ȱȱȱȱȱ
ûȱ ûûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱȱȱȱȱȱȱǿŗǰȱŘǰȱȱǯǯǯǰȱŗŖŖȀȱȱǰȱȱȱ
ȱȱǯȱ
ȱ
ȱ ŗDZȱ ȱ ȱ ȱ ȱ ȱ řŚřȱ ȱ ȱ ȱ £ ȱ Śşǰȱ ȱ ûȱ ȱ ȱ
DZȱȱ£ȱãǰȱřŚřȱ£ȱǰȱȱǰȱȱȱŝȱȱŚşȱȱ
£ȱ ǯȱ ȱ £ȱ ãǰȱ ȱ Śşȱ £ȱ ǰȱ ȱ ȱ £ȱ ȱ
ȱ Śşǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ûȱ ǻȱ £ ȱ ȱ ȱ
ȱȱǷǼǯȱ
ȱ ŘDZȱ ȱ ȱ ȱ ȱ ŗşŚȱ ȱ ȱ ȱ £ ȱ ŗŝŞǰȱ ȱ ȱ ûȱ ȱ
ȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ Řȱ ȱ şŝȱ ȱ ǯȱ ȱ
£ ȱȱȱȱȱãȱŘȱȱŞşǯȱȱ ȱ ǰȱȱȱ£ ȱȱ
ȱǰȱǰȱȱȱȱûǰȱȱ ȱȱ£ ȱǯȱ
ȱřDZȱ ȱ DZȱŗřŞȱȱŘśŞǯȱȱŗřŞȱ£ȱǰȱȱ ȱȱ
ãȱǻŜǰȱŘřǼǰȱǻřǰȱŚŜǼǰȱǻŘǰȱŜşǼǰȱǻŘǰȱřǰȱŘřǼǯȱȱãȱǰȱȱȱȱ
ȱȱŜȱȱŘřȱȱȱȱȱ£ ȱȱȱřȱȱŞŜǯȱȱȱ
ȱ£ ȱȱȱȱȱ ȱȱǯȱ
ȱŚDZȱ ȱ DZȱŗŘřŜȱȱŗŖŖǯȱȱȱȱãǰȱȱŗŘřŜȱ
£ȱǰȱȱûȱȱȱǯȱȱȱȱȱŗŖŖȱ£ȱ£ǰȱȱȱ
ȱãȱǻŗŖŖǼǰȱǻśǰȱŘŖǼǰȱǻŚǰȱŘśǼǰȱǻŘǰȱśŖǼȱȱǻŘǰȱśǰȱŗŖǼǰȱȱȱȱ£ ȱȱ
ȱȱ ǯȱ
ȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ãǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ãǯȱ DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ǰȱȱȱȱȱǯȱDZȱûȱȱȱȱȱȱ
ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯDZȱ
198
Grundlegende Algorithmen mit Java
ȱ
Der erste Spieler gewinnt!
Der zweite Spieler gewinnt!
Der erste luegt! Der Zweite gewinnt!
Der zweite luegt! Der Erste gewinnt!
Beide luegen! Unentschieden!ȱ
ȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱŗȱȱŗŖŖȱ£ȱ ȱãǰȱ ȱȱȱȱȱ
ãđȱ ȱ ǰȱ ȱȱȱȱǯȱȱȱȱ£ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǰȱ
ȱ £ ȱ ȱ ǯȱ ȱ ǮDer Zweite hat sich verrechnet! Der Erste
gewinnt!” §ȱ ȱ ȱ ǯȱ ȱ đȱ ȱ ȱ ǰȱ
ȱȱ ȱȱûȱȱȱ ȱǯȱDZȱ
ȱ
orangen.in
orangen.out
Der zweite Spieler gewinnt!
110 119
Der Zweite luegt! Der Erste gewinnt!
294 202
Der zweite Spieler gewinnt!
343 49
Der erste Spieler gewinnt!
610 3599
Der zweite Spieler gewinnt!
138 258
Beide luegen! Unentschieden!
941 2234
Der Erste luegt! Der Zweite gewinnt!
1236 100
Der erste Spieler gewinnt!
6231 1500
Beide luegen! Unentschieden!
151 127
Der Zweite luegt! Der Erste gewinnt!
1 101
ǻȱȱȱȱȱȱȱȱǰȱŗşşŞǰȱ £Ǽȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ £ȱ ȱ ǰȱ ûȱ ȱ ȱ ȱ ȱ ȱ ãȱ
£ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǿŗǰȱ Řǰȱ dzǰȱ ŗŖŖȀȱ Ȭ
ȱǯȱȱȱȱûȱȱȱȱ£ȱǰȱȬ
ȱ ȱȱȱȱȱȱȱãđȱȱȱȱȬ
ȱ ȱ ȱ ȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ ȱ ǻȱ Ȭ
ȱȱȱ£ ȱȱȱȱǼǯȱ
ȱȱȱ ȱȱȱȱ £ȱȱ ȱȱȱȬ
ȱȱûȱǯȱȱȱȱȱȱǻȱȱȱȱ
ȱǼȱȱûȱǯȱȱ ȱȱȱȱȱȬ
ȱ ȱ ȱ ¢ȱ ǀǀ ǁǁȱ ǯȱ ȱ ȱ ǻȱ Ǽȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
Ȭȱ ǻǼȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻǼȱ ûǯȱ
7
Backtracking
199
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ ȱ ȱ ȱ ǻ¡ǯǻǼƽƽǰȱ ȱ ȱ ȱ ǯǻȬŗǼȱ ȱ ǰȱ ȱ
ȱȱ ǰȱȱ ȱȱ¡ǯǻǼƽƽǰȱ ȱȱȱȬ
ȱ ȱǼǯȱȱȱǻǼȱȱ ȱDZȱ
• ȱȱȱȱ ȱ ȱȱȱǯȱ
• ȱȱƽȱǰȱȱȱ ȱȱȱûȱǰȱȱȱȱȱȱȬ
ȱ£ûȱ ǯȱȱ
• ȱȱƾȱǰȱȱ£ȱ ȱ¡ǽǾȱ£ȱȱȱȱȱȱǯȱ
• ¡ǽǾȱ ȱ ǰȱ ǯǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ȱǻǼȱȱƸŗȱǯȱ
• đȱ£ȱ ȱ¡ǽǾȱȱǯȱȱȱȱǻǽȬŗǾȱȱǼȱãȬ
ȱȱȱȱȱ ȱȱ ǰȱ ȱǻȉȱǽȬŗǾǼȱ
ȱȱȱȱȱǻȱãȱ£ȱȱȱȱûǼǯȱȱȬ
n
= 1 ȱǻȱ ȱǽȬŗǾȱȱ£ȱ
p ⋅ a[k − 1]
n
ȱȱȱǼȱȱ
> a[ k − 1] ȱǻȱȱȱȬ
p ⋅ a[ k − 1]
ȱȱǰȱȱ ȱ
ȱ ȱȱ£ǼDZȱ
if (0==(n/p)%a.get(k-1)) {
ȦȦȱȱȱȉǽȬŗǾ
x.set(k);
if (1==(n/p)/a.get(k-1)||(n/p)/a.get(k-1)> a.get(k-1))
{…}…
ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £Ȭ
ûDZȱǻǰȱǼǯȱ
ȱ
ȱȱǻǼȱȱȱȱȱȱȱŗȱȱ
Řǰȱ ȱ £ ǯȱȱȱȱ ȱǯȱȱ ȱȱ ȱȱ
ȱȱȱȱȬǯȱȱ£ȱȱǰȱȱȱȱȬ
ȱ ǻǼȱ ȱ ȱ ȱ Ȭȱ ȱ ǯȱ ȱ ȱ
ǻǼȱ ȱ ȱ £ûǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǯȱȱȱ ǻǼȱȱǰȱȱȱȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ £ȱ ȱ ȱ ȱ ȱ £ ȱ ȱ
ȱȱǻȱȱ£ ȱǰȱȱȱȱȱȱǼǯȱȱ
ȱ
Programm 1
import java.io.*;
import java.util.*;
200
Grundlegende Algorithmen mit Java
public class P11Orangensport {
private static final String FileInputName = "orangen.in";
private static final String FileOutputName = "orangen.out";
static void makeDecision(int n1, int n2, PrintStream out) {
List<Set<Integer>> b = new SetsList(n1).getValue();
List<Set<Integer>> c = new SetsList(n2).getValue();
if (b.isEmpty() && c.isEmpty())
out.println("Beide luegen! Unentschieden!");
else if (b.isEmpty())
out.println("Der Erste luegt! Der Zweite gewinnt!");
else if (c.isEmpty())
out.println("Der Zweite luegt! Der Erste gewinnt!");
else if (n1 < n2)
if (isADisjointCombination(b, c))
out.println("Der zweite Spieler gewinnt!");
else
out.println("Der erste Spieler gewinnt!");
else if (isADisjointCombination(b, c))
out.println("Der erste Spieler gewinnt!");
else
out.println("Der zweite Spieler gewinnt!");
}
private static boolean isACommonElement(Set<Integer> setA,
Set<Integer> setB) {
for (Integer el : setA) {
if (setB.contains(el)) {
return true;
}
}
return false;
}
private static boolean isADisjointCombination
(List<Set<Integer>> b, List<Set<Integer>> c) {
boolean flag = false;
short bSiz = (short) b.size(), cSiz = (short) c.size();
for (short i = 0; !flag && i < bSiz; i++)
for (short j = 0; !flag && j < cSiz; j++)
if (!isACommonElement(b.get(i), c.get(j)))
flag = true;
return flag;
}
public static void main(String[] args) throws IOException {
7
Backtracking
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNextInt()) {
int n1 = sc.nextInt();
int n2 = sc.nextInt();
makeDecision(n1, n2, out);
}
} finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
class SetsList {
private BitSet x;
private List<Integer> a;
private List<Set<Integer>> value;
SetsList(int n) {
this.value = new ArrayList<Set<Integer>>();
this.a = new ArrayList<Integer>();
this.x = new BitSet();
for (int i = 2; i <= 100; i++)
if (0 == n % i)
a.add(i);
back(n, 1, this.value);
}
List<Set<Integer>> getValue() {
return value;
}
private void addSet(int k, List<Set<Integer>> b) {
Set<Integer> auxSet = new HashSet<Integer>();
for (int i = 1; i < k; i++)
if (x.get(i))
auxSet.add(a.get(i - 1));
b.add(auxSet);
}
201
202
Grundlegende Algorithmen mit Java
private void back(int n, int k, List<Set<Integer>> b) {
int p = 1;
int aSiz = (int) a.size();
for (int j = 1; j < k; j++)
if (x.get(j))
p *= a.get(j - 1);
if (p == n) {
addSet(k, b);
} else if (k <= aSiz)
for (int i = 0; i < 2; i++) {
x.set(k, 0 != i);
if (i == 0)
back(n, k + 1, b);
else if (0 == (n / p) % a.get(k - 1)) {
x.set(k);
if (1 == (n / p) / a.get(k - 1)
|| (n / p) / a.get(k - 1) > a.get(k - 1))
back(n, k + 1, b);
}
}
}
}
ȱ
ȱ§ȱȱȱȱȱȱǰȱȱ ȱǯȱȱûȱ
ȱǯȱûȱȱȱȱȱ£ȱ£ȱȱǯȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱ ȱȱ ȱ
ǯǯȱȱ DZȱȱȱȱ£ǰȱ ȱȱ ȱȱ ǯȱȱ
ȱȱ ȱ£ȱȱȱǀǁȱ£ûǯȱȱȬ
ȱȱȱŗȱȱȱȱǰȱȱȱ ȱȱȱȬ
ȱȬȱǻǼȱǯȱȱȱ§ȱȱȱȱ
ȱ£ȱȱȱȱǻȱȱȱȱȱǼǰȱȱ
ȱȱȱûȱ ȱǰȱȱȱǻǼȱȱȱȱȱȬ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ȱ ȱDZȱ
ȱ
• §ȱ ȱȱǰȱȱȱȱȱȱǯȱûȱȱȬ
ȱȱȱȱȱȱȱȱ ȱȱǰȱȱãđȱȱȱ
ǰȱȱȱȘȱȱȱȱȱǯȱ ȱȱȱȱȱȬ
ȱ ǻûȱ ȱ ȱ Ɩȱ ȱ Ǽȱ ȱ £ȱ ȱ ȱ £ûǯȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ȱ ǻǼǯȱ đȱ ȱ ȱ ȱ
ȱȱȱȱȱǯȱ
7
Backtracking
•
203
ȱ ȱǰȱȱȱȱȱȱȱȱȱŗŖŖȱǰȱ
ȱȱȱȱȱǯȱ ȱȱȱ ȱȱ ȱȱȱȬ
ȱȱ£ȱǻǼǰȱȱȱȱȱȱ ȱûȱȱ
ȱȱȱȱȱȱ§ǯȱ
ȱ
ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ ȱ ŗȱ ȱ
Řǰȱ ȱ£ ǯȱȱȱȱ ȱǯȱ £ȱ ȱ£§ȱȱãȱ
ȱ ȱ ŗȱ ȱ Řȱ ȱ ȱ ȱ £ǻǼȱ ǯȱ ȱ
ȱ ǻǼȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱǰȱȱ£ȱȱȱȱȱ£ ȱȱȱȱǻȱȱ£ ȱ
ǰȱȱȱȱȱȱǼǯȱȱȬȱǻȱ
Ǽȱ ûǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱǯȱȱȱȱȱǰȱ ȱȱȱȱǯȱ
ȱ
Programm 2 (Dr. Eric Müller)
import java.io.*;
import java.util.*;
public class P11Orangensport02 {
private static final String FileInputName = "orangen.in";
private static final String FileOutputName = "orangen.out";
private static final int BOUND = 100;
static private List<BitSet> factorizations(int n)
{
List<BitSet> list = new ArrayList<BitSet>();
if (n == 1) {
BitSet one = new BitSet(2);
one.set(1);
list.add(one);
}
else
back(n, 2, new BitSet(BOUND+1), list);
return list;
}
static void back(int n, int k, BitSet found, List<BitSet> l) {
for (int f = k; f < BOUND && f*f < n; f++) {
if (n%f == 0) {
found.set(f);
back(n/f, f+1, found, l);
found.clear(f);
}
204
Grundlegende Algorithmen mit Java
}
if (n <= BOUND) {
BitSet copy = (BitSet) found.clone();
copy.set(n);
l.add(copy);
}
}
static void makeDecision(int n1, int n2, PrintStream out) {
List<BitSet> b = factorizations(n1);
List<BitSet> c = factorizations(n2);
if (b.isEmpty() && c.isEmpty())
out.println("Beide luegen! Unentschieden!");
else if (b.isEmpty())
out.println("Der Erste luegt! Der Zweite gewinnt!");
else if (c.isEmpty())
out.println("Der Zweite luegt! Der Erste gewinnt!");
else if (n1 < n2)
if (isADisjointCombination(b, c))
out.println("Der zweite Spieler gewinnt!");
else
out.println("Der erste Spieler gewinnt!");
else if (isADisjointCombination(b, c))
out.println("Der erste Spieler gewinnt!");
else
out.println("Der zweite Spieler gewinnt!");
}
private static boolean isADisjointCombination
(List<BitSet> list1, List<BitSet> list2) {
for (BitSet b: list1)
for (BitSet c: list2)
if (!b.intersects(c))
return true;
return false;
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
while (sc.hasNextInt()) {
int n1 = sc.nextInt();
int n2 = sc.nextInt();
makeDecision(n1, n2, out);
7
Backtracking
205
}
} finally {
if (sc != null) sc.close();
if (out != null) out.close();
}
}
}
ȱȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
śǯ
Ŝǯ
ŝǯ
Şǯ
ȱ
ȱ ǰȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱǯȱ
£ȱȱȱȱǻǼȱȱȱȱȱȱ
ȱ ǻǼȱ ȱ ȱ ȱ ǯǯǯȱ ȱ ȱ ȱ
ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǯȱ
ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯǯȱ ǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ£ǯȱ
ȱ ȱ ȱ ȱ ȱ Řȱ ȱ ȱ ȱ £ ȱ ȱ ȱ ǻǼȱ
£ǵȱ ȱ ȱ ȱ ȱ ȱ £ȱ ǻǼȬȱ ȱ
ȱȱȱ£ȱ ȱǯȱ
ȱ ȱ ȱ £ ȱ ȱ ȱ ȱ ȱ
ǯǯǀ ǁȱ ȱ ǯǯǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
£ǯȱ ȱ ûȱ ȱ ȱ ȱ ȱ ǻǼȬȱ
ȱ ǯǯǰȱ ǯǯǀ ǁȱ ȱ ǯǯ¢ǵȱ ȱ ȱ
ȱȱȱȱǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ûȱ ãȱ ûȱ ȱ
Ȭȱ ȱ ȱ ǻ ȱ ãȱ ȱ ûȱ ȱ Dzȱ
ȱȱûȱȱȱȱ ãȱǰȱȱȱȱûȱǮȬ
ȃȱȱǮȃǼǯȱ ȱȱȱǯȱ
ȱȱȱȱȬȱȱȱǯȱ
ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ
ȱȱȱȱȱǿŗǰȱŘǰȱdzǰȱŗŖŖȀȱǯȱȱ
206
Grundlegende Algorithmen mit Java
Problem 12. Testmusterkompaktierung
ȱȱȱȱǰȱȱȱȱȱ£ȱȱȱ′ȱ
ȱ§ȱ£ǰȱȱȱȱûȱȱȱȱȱȱȱ
ȱȱ′ȱǯȱȱȱȱȱǰȱȱȱȱȱȱȱƽȱǿȁŖȂǰȱȁŗȂǰȱ
ȁȂǰȱ ȁȂǰȱ ȁȂȀȱ §ǯȱ ȱ ȱ ȱ ǯȱ DZȱ ŖŗŖŗǰȱ
ŗŖŖŖŗŗŗǯȱ
ȱ
ȱ ŗǯȱ ȱ ǯȱ ȱ ǰȱ ȱ £ ȱ ȱ ȱ ǰȱ
ȱȱȱȱȱȱȱȱȱȱȱȁȂȱǻȂȱǼȱǯȱ
ȱ£ȱȱȱȱȁ≡
≡Ȃȱȱȱ §ȱȱȁ≠ȂǯȱȱȱȬ
ȱȱȱȱǰȱȱ£ȱǻǼȱȱ£ȱǰȱ ȱ
ȱȱȱǰȱȱ ȱȱ£ȱȱȱȱǻǼǰȱȱȱȁȂȱ
ǯȱȱ §ȬȱȱȱȬȱȱȱȱȱȱ
ǻȁȘȂȱȱȱǼǯȱ
§ȬȬȱ
≡
0
1
U
Z
X
0
0
*
*
*
0
1
*
1
*
*
1
U
*
*
U
*
U
Z
*
*
*
Z
Z
X
0
1
U
Z
X
ȱ
ȱ Řǯȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ ȱ
ǰȱȱȱȱȱȱȱȱȱȱǰȱȱȱȱȱȬ
ȱȱ£ ȱȱǰȱȱǯȱȱ£ ȱȱȱ£ȱȱ
ȱȱǰȱȱȱȱ£ ȱȱȱȱȱȱȬ
ȱ£ǯȱDZȱȱȱŗȱƽȱŗŖŖȱȱŘȱƽȱŖŗŖȱȱǰȱ ȱ
ŗǻǼȱ≡
≡ȱŘǻǼǰȱûȱȱȱ∈ȱǿŗǰȱŘǰȱdzǰȱŝȀǯȱǻŗǰȱŘǼȱƽȱŗŖŗŖǯȱ
ȱ
ȱ ȱȱûȱȱȱȱȱȱǯȱ DZȱ
ȱȱȱǯȱȱȱȱȱȱ§ǰȱȱȱȱǻãȬ
ȱŚŖȱǰȱȱ¡ȱ§ȱ§ȱŗŖŖŖȱǼǯȱDZȱȱȱȱȱ
ȱǯȱȱȱȱȱȱȱȱȱȱǻ£ȱȱ
§ȱȱǼǰȱȱȱ£ ȱȱȱ£ȱȱȱȱȱȬ
ȱȱȱ£ȱȱ£ǰȱȱȱȱȱȱ£ȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ǯȱ ȱ ǰȱ ȱ ȱ
£ȱȱȱȱȱǯȱDZȱ
ȱ
ȱ
7
Backtracking
207
tests.in
UU0XXZZU
XUU0XX11
XXUXZXXX
UUU0ZZ11
0XX111XX
XUU0XX11
U0XXXUXU
XXXX1XXX
UXXXXZZU
011111ZZ
0XX1XXXX
XXUXZXXX
U0UXZU0U
XUUXZX1X
0UXZX11U
tests.out
15 8
5 33.3333%
UU0X1ZZU
011111ZZ
U0UXZU0U
0UUZZ11U
UUU0ZZ11
ǻȱǰȱ ã ȱ¢ǰȱȱ đǼȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱȱ ȱȱ§ȱȱ§£ǰȱȱȱǰȱȱãȱ
£ȱǯȱ
ȱ
£ȱŗǯȱȱŖȱ≠ȱŗȱǻȱǼǰȱŖȱ≡ȱŘȱǻǼȱȱǻŖǰȱŘǼȱƽȱřǰȱȱřȱ
≠ȱŗǯȱȱ
ǯȱ ȱ Ŗȱ ȱ ŗȱ ȱ ȱ ǰȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
¡ǰȱȱȱŖǽǾȱ≠ȱŗǽǾǯȱȱȱȬȱǻŖǰȱŘǼȱƽȱřȱǰȱȱ
řǽǾȱƽȱŖǽǾǰȱȱřǽǾȱ≠ȱŗǽǾǰȱ ȱȱȱȱȁȂȱǯȱȱǰȱȱŗȱȱřȱȱ
ȱǯȱ÷ȱ
ȱ
£ȱŘǯȱȱŖȱ≡ȱŗȱȱǻŖǰȱŗǼȱƽȱŘǰȱŘȱ≡ȱřȱȱǻŘǰȱřǼȱƽȱŚǰȱȱȱǰȱȱŖȱ
≡ȱŚȱȱŗȱ≡ȱŚǯȱȱ
ǯȱ ȱ ȱ ȱ ȱ Ŗȱ ȁȂȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ Śȱ ǯȱ ȱ ȱ ȱ ȁȂȱ ǰȱ ȱ ȱ ȱ Ȭȱ
ȱȱȱŚȱ£ǯȱ÷ȱ
ȱ
£ȱřǯȱȱt0 ≡ t1 t1 ≡ t2ǰȱȱȱǰȱ t0 ≡ t2.
Beweis. : ŖȱƽȱŗǰȱŗȱƽȱǰȱŘȱƽȱŖȱǻȱȱǷǼǯȱ÷ȱ
ȱ
ȱ ȱ ȱ £ȱ ãǰȱ ȱ ȱ ȱ ȱ Ȭȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ £ȱ
ǰȱȱ£ ȱȱȱȱȱ£ȱȱ£ȱ ǯȱ
ȱȱ ȱȱûȱȱ£ȱȱȱ ǯȱȱ
208
Grundlegende Algorithmen mit Java
ȱ ȱ ȱûǰȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ǰȱ ȱ ȱ
ȱȱȱ£ ȱǻȱȱȱȱȱǷǼǯȱȱȱȱȬ
ȱȱǰȱȱȱȱȱǰȱȱȱȱ£ȱȱãȱãǯȱ ȱ
ȱ ȱ ûȱ ȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ û£ȱ ȱ ȱ ȱ ãȬ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ ȱ Ȭ
ǯȱȱȱû£ȱǰȱȱ ȱȱȱȱ£ǯȱȱ
ȱȬDZȱ
ȱ
ȱ ȏ ȏȏǻȱȱǰȱǭȱȱǼȱ
ȱȱ
ȱ
ȱ←ȱȱ
ȱ
ȱǻƽŗǰ£ǻǼȬŗDzȱȱŗǼȱ¡ȱ
ȱ
ǻȱƽƸŗǰȱ£ǻǼDzȱȱŗȱǼȱ¡ȱ
ȱ
ȱ
ȱȱ ǻȱȱǼȱȱ
ȱ
ȱ←ȱȱ
ȱ
ȱ
ȱ
ȱ←ȱǻǰȱǼȱ
ȱ
ȱ
ȱ
ǯǻǼȱ
ȱ
ȱ
ȱ
ǯǻǼȱ
ȱ
ǯǻǼȱ
ȱ
ȏ ȏȏǻǰȱȱǼȱ
ȱ
ȱȱ
ȱȱȏ ȱ
ȱ
ȱ
ȏȱ
ȱ
ȏȱ
ȱ
ȱǻǼȱ¡ȱ
ȱ
ȱ
ǻȱ£ǻǼȱǁȱ£ǻǼȱǼȱȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱ←ȱ¢ȏǻȱȱǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏ ȱȱȱ
ȱ
ȱȱDzȱ
ȱ
ȏ ȱ ȱ
ȱ
ȏ
ȱȏ ȏȏȱ
ȱ
ȱ
ȱȱǯȱȱȱȱǰȱ ȱȱȱȱȱȬ
ȱ ȱ ǻȱ £ȱ ȱ £ ȱ ȱ ȱ ȱ ȱ £Ǽǰȱ
ȱȱȱȱ §ȱ ȱǯȱȱ
ȱ
¡§ȱȱǯȱȱȱȱȱ¡ȱȱ ãȱȱǻ£ȱ
ȱ ȬǼǯȱȱ £ȱȱȱȱ §ȱȱDZȱȱ
n
n(n − 1) (n − 1)(n − 2) (n − 2)(n − 3)
k (k − 1) n!⋅(n − 1)!
2 ⋅1
ǯȱȱ
⋅
⋅
⋅ ... ⋅
=
=
2
2
2
2
2
2 n −1
k =2
∏
7
Backtracking
ȱ ¡§ȱȱȱ O(
209
n!⋅(n − 1)!
) ǯȱ÷ȱȱ
2n
ȱ ȱȱȱǻǼȱǻûǰȱȱ£ ȱȱȱǼǰȱ
ǻǼȱǻûǰȱȱ£ ȱȱȱǼǰȱǻǼȱǻûȱȱȬ
ȱȱ£ ȱȱǼȱȱǻǼȱǻûȱȱȬȱȱ£ ȱ
ȱǼȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P12Compactation {
private static final String FileInputName = "tests.in";
private static final String FileOutputName = "tests.out";
private static boolean compatibleChars(char c1, char c2){
return c1 == c2
|| c1 == 'X' || c2 == 'X';
}
private static boolean compatibleLines(String str1,
String str2) {
int len = str1.length();
if (len != str2.length()) return false;
for(int i = 0; i<len; i++)
if(!compatibleChars(str1.charAt(i),
str2.charAt(i)))
return false;
return true;
}
private static char mergeChars(char c1, char c2) {
return
compatibleChars(c1, c2)?('X' == c1 ? c2 : c1) : '*';
}
private static String mergeLines(String str1, String str2)
{
int len = str1.length();
if (len != str2.length()) return null;
char chars[] = new char[len];
for (int i = 0; i < len; i++) {
chars[i] = mergeChars(str1.charAt(i),
str2.charAt(i));
}
return new String(chars);
210
Grundlegende Algorithmen mit Java
}
private static void recExactCompact(List<String> v,
List<String> vRet) {
List<String> vCopy = new ArrayList<String>(v);
boolean compact = true;
for (int i = 0; i < vCopy.size() - 1; i++)
for (int j = i + 1; j < vCopy.size(); j++)
if (compatibleLines(vCopy.get(i),
vCopy.get(j))) {
compact = false;
String str = mergeLines(vCopy.get(i),
vCopy.get(j));
vCopy.remove(i);
vCopy.remove(j - 1);
vCopy.add(str);
recExactCompact(vCopy, vRet);
}
if (compact) {
if (vRet.size() > vCopy.size()) {
vRet.clear();
for (int i = 0; i < vCopy.size(); i++)
vRet.add(vCopy.get(i));
}
return;
}
}
private static double doRecExactCompact
(List<String> v, List<String> vRet, PrintStream out) {
recExactCompact(v, vRet);
out.print(v.size()); out.print(' ');
out.println(v.get(0).length());
out.print(vRet.size()); out.print(' ');
out.print(vRet.size()*100.0/v.size());
out.println('%');
out.println();
for (String s : vRet) {
out.println(s);
}
return vRet.size()*100.0/v.size();
}
public static void main(String[] args) throws IOException {
Scanner sc = null;
PrintStream out = null;
try {
7
Backtracking
211
out = new PrintStream(new File(FileOutputName));
sc = new Scanner(new File(FileInputName));
List<String> v = new ArrayList<String>();
while(sc.hasNext()) {
v.add(sc.next());
}
List<String> vRet = new ArrayList<String>(v);
doRecExactCompact(v, vRet,out);
}
finally {
if (sc != null) {
sc.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgaben
ŗǯ
Řǯ
£ȱȱȱ ȱȱȱȱ¢ȱǽǾǯȱ
ȱȱȱDZȱȱ
Ǽ
ȱȱȱ£ȱȱȱȱȱȱ ȱ ȱ
ǯȱDZȱûȱǯȱȱȱȱȱȱ£ȱŚŗǯȱ
Ǽ ȱ ȱ ȱ ȱ ȱ ȱ ȱ DZȱ £ȱ ȱ
ǰȱȱ§ȱȱȱȱȱȱȱȱǯȱ
Ǽ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȏȱ ǻȱ ȱ ȱ ȱ £ ȱ Ȭȱ ȱ
ȱ
ȱ §Ǽȱ ȱ ǯȱ ȱ ûȱ
ȱȱȏȱŞDZȱ
ȱȱ
5 Zeilen
(Tests),
5 Spalten
(Länge)
15 Zeilen
(Tests),
9 Spalten (Länge)
1XUU1
UX1U0
Z10XX
000X0
0XZ0U
XXXXZXXXX
X1X1ZXXXX
X1X1ZXX1X
X1X1Z111Z
XXXXZX1XX
XXXXZXXXX
11X1Z111Z
X1X1ZXX1X
212
Grundlegende Algorithmen mit Java
XXX1ZXX1X
1000U0UU0
XXXXZXXXX
X00ZU0ZZU
XXXXZ11XX
XXXXZXXXX
X1X1ZXXXX
ȱ
řǯ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ ȱ ¡ȱ ¡§ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ £ §ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ £ȱ
ǰȱ ãȱ ȱ ȱ ¢Ȭȱ ǰȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ûǯȱ ȱ ȱ ûȱ
ȱ ¢ȬDZȱ
ȏ ȏȱ
ȱǽŗǯǯǾȱ
ȱȱ
ȱ←ȱȱȱ
ȱǻȱǼȱ¡ȱȱ
ȱ
ǻȱ∃ǰȱDZȱȱȱȱǼȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱȱǻǰȱǼȱ¡Ǽ
ȱ
ȱ
ȱ←ȱȱ
ȱ
ȱ
ȱ←ȱǻǰȱǼȱ
ȱ
ȱ
ǯǻǼȱ
ȱ
ȱ
ǯǻǼȱ
ǯǻǼȱ
ȱȱ
ȏ ȱ
ȱ
ȱ¡ȱ
ȱ
ȱ
ȱ←ȱȱ
ȱ
ȏȱ
ȏȱ
ȏ ȏȱ ȏȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱãđȱǯȱȱ
Ǽ ȱȱȱǰȱȱȱȱǯȱȱ
Ǽ §£ȱȱȱȱȱȱȱȱȱȱŗȱ
ȱȱ ¢Ȭǯȱȱ
Ǽ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £§ȱ ȱ
£ȱȱȱȱ ¢Ȭȱ£ǯȱȱȱȱȱ
7
Backtracking
213
£ȱ ȱ ¢Ȭǯȱ ȱ ȱ ãȱ ȱ ȱ
ȱȱȱȱ£ȱ
ȬȱȏȱŘśǰȱ
Ȭȱ £ȱ ȱ ŗŖŖȱ ȱ ŗŖŖŖȱ ȱ ȱ ȱ ŗŖŖȱ ǻŗŖŖȏ¡¡¡ǯ¡ȱ ȱ
ŗŖŖŖȏ¡¡¡ǯ¡Ǽǰȱ
Ȭȱ §ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ǻ§ȱ ȱ Ǽȱ ȱ
ŗŗśȱȱşŗśȱȱȱȱŘŖŖȱǻ¡¡¡ȏŗŗśǯ¡ȱȱ¡¡¡ȏşŗśǯ¡Ǽǯȱ
ȱȱǯȱãȱȱDZȱ
ȱ
report.out
file_name
#lines #cols #comps comp_rate time(sec)
f100_115.txt
100
115
549
36.00%
1
f100_315.txt
100
315
850
24.00%
1
f100_515.txt
100
515 1503
20.00%
1
f100_715.txt
100
715
647
28.00%
1
f100_915.txt
100
915
973
26.00%
2
…
Śǯ
ȱ
f600_115.txt
600
115 35915
33.83%
82
f600_315.txt
600
315 29436
30.33%
123
f600_515.txt
600
515 17916
29.83%
163
f600_715.txt
600
715 37335
30.17%
190
f600_915.txt
600
915 8452
26.83%
186
…
f1000_115.txt 1000
115 16218
32.80%
213
f1000_315.txt 1000
315 89951
33.90%
394
f1000_515.txt 1000
515 28579
29.70%
813
f1000_715.txt 1000
715 258987 17.90%
227
f1000_915.txt 1000
915 86154
16.30%
495
ǻǛȱȱȱ£ȱȱûȱȱǷǼȱȱ
ȱ
ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ¢Ȭǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱ ȱ ȱ ȱ £ǰȱ ȱ ȱ ȱ
ȱ §đȱ ȱ ȱ £ǰȱ ȱ ȱ ȱ
ȱȱȱȱǯȱȱ ǯȱȱȱȱ£ǯȱ
ǯDZȱ ȏȱ śŖDzȱ £ȱ śȱ Ȭȱ řśȱ ȱ £ȱ śȱ Ȭȱ şȱ ǻȱ ȱ
ǼȱȱȱȱȱȱǯȱȱȱȱǮȘȘȄȱȱ
§ǰȱ ûȱ ȱ ȱ ȏȱ ȱ ȱ ãȱ ȱ ȱ Ȭ
¢ȏȱ ǯȱ ȱ ȱ ȱ ȏǰȱ ȱ £ȱ ȱ
ȱ ȱ ȱ §ǯȱ ȱ £ȱ ȱ ȱ ȱ ȱ
ȱ ȱȱȱ ¢Ȭǵȱȱȱǰȱ
ȱǰȱûȱȱǷȱ
214
Grundlegende Algorithmen mit Java
report.out
file_name
f_5_5.txt
f_5_6.txt
f_5_7.txt
…
f_11_7.txt
f_11_8.txt
f_11_9.txt
f_12_5.txt
…
f_20_6.txt
f_20_7.txt
f_20_8.txt
…
f_35_5.txt
f_35_6.txt
f_35_7.txt
f_35_8.txt
f_35_9.txt
#lin #col
5
5
5
6
5
7
GREEDY_COMPACT
#cps c_rate
t(s)
3
60.00%
0
1
80.00%
0
4
60.00%
0
BACK_COMPACT
c_rate
t(s)
60.00%
0
80.00%
0
60.00%
0
11
11
11
12
7
8
9
5
12
13
4
58
54.55%
45.45%
63.64%
16.67%
0
0
0
0
45.45%
45.45%
63.64%
16.67%
0 **
0
0
0
20
20
20
6
7
8
48
31
61
55.00%
35.00%
50.00%
0
0
0
55.00%
35.00%
50.00%
0
3
1
35
35
35
35
35
5
6
7
8
9
90
201
150
71
116
54.29%
40.00%
40.00%
57.14%
51.43%
0
0
0
0
0
45.71% 395 **
37.14% 3689 **
40.00% 2677
57.14%
82
51.43% 254
ȱ
śǯ
Ŝǯ
ȱȱȱȱ¢ȱǰȱ ȱȱ ȱǿŖǰȱŗǰȱǰȱǰȱȀȱȱ
śȱ ȱ ȱ ǻǯǯȱ ȱ ȱ ȱ Şȱ ȱ ûȱ ȱ ǰȱ ȱ ȱ řǼǯȱ
ȱȱȱǰȱȱȱȬȱǯȱȱ
ȱȱȱȱǰȱȱȱȱȱ£ȱȱȱ
ǰȱ ȱ ȱ ȱ ȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱ ǯȱ
Problem 13. Sudoku
ȱȱȱȱȱȱȱãȱȱȬ§ȱȱȬ
ȱ ȱ ûȱ ǵȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ şȱ ȱ ȱ şȱ
ȱǰȱȱȱȱ£ȱûǰȱȱşȱãȱȱȱř×řȱǻȱ
Ǽǯȱȱȱȱȱȱȱȱȱŗȱȱşȱǯȱȱ§Ȭ
ȱȱȱȱȱȱȱûǰȱȱȱȱǰȱȱȱȱ
ȱȱȱȱȱȱȱȱǻȱȱȱ ȱȱ
ȱ ǮȬȃǼǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻȬ
ȱ£ ȱŘŘȱȱřŜǼǰȱȱ ȱȱǰȱȱȱ£ȱãǯȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ãȱ ȱ ȱ ȱ ȱ
ȱȱ¢ȱ ǯȱ
ûûȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ȱ ȱ ǻŗŝŖŝȬŗŝŞřǼȱ §ǯȱ ȱ ǰȱ ȱ ȱ
ȱ ·ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ãđȱ şȱ ǰȱ ȱ ȱ ãđȱ ȱ
ȱȱȱȱđȱȱȱãǯȱ
7
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
Backtracking
215
ȱ ȱ ȱ
ȱ ȱ ȱ
şȱ řȱ ś
śȱ ȱ
ȱ ȱ
Śȱ ȱ
Ŝȱ ŝȱ ş
ȱȱȱȱ ȱ ȱ
ȱ ŗȱ ȱ
ȱ
ȱ
ȱ
ŝȱ ȱ
Śȱ ȱ
ȱȱȱ ȱ
ȱ
ȱ
ȱ
Ş
ř
ȱ
şȱ
ȱ
ȱ
řȱ Ŝ
śȱ Ś
ŝȱ Ş
ŗȱ Śȱ ŝ
Şȱ Ŝȱ Ř
şȱ řȱ ś
śȱ Řȱ Ş
ŝȱ şȱ ř
Śȱ Ŝȱ ŗ
şȱ řȱ Ŝ
ŗȱ śȱ Ś
Řȱ ŝȱ Ş
Şȱ ȱ
ȱ ȱ
ŝȱ Ś
ȱ
ȱ
ȱ
ȱ ś
Şȱ ȱ
ȱ Ř
Ŝȱ ŝȱ ş
řȱ Řȱ Ś
śȱ ŗȱ Ş
řȱ Şȱ Ř
şȱ ŗȱ ś
Ŝȱ ŝȱ Ś
Śȱ ŗȱ ś
Ŝȱ Şȱ ŝ
řȱ şȱ Ř
Řȱ śȱ ȱ
ȱ ȱ ȱ
ŗȱ ȱ ȱ
ȱ
ŝȱ
ȱ
ȱ ř
Řȱ ȱ
ȱ ȱ
ŝȱ şȱ ŗ
Śȱ śȱ Ŝ
Řȱ Şȱ ř
Řȱ śȱ Ŝ
Şȱ řȱ ş
ŗȱ Śȱ ŝ
Şȱ Śȱ ř
ŝȱ Řȱ ŗ
śȱ Ŝȱ ş
ȱ
ȱûȱȱȬ§ȱ
ȱȱȱȱȱãǰȱȱȱȱȱǯȱȱǯȱȱȬ
ȱȅȘȂȱ ȱûȱȱȱǯȱȱ ȱȱãȱãȱȱȱȱ
ǯȱ ȱȱȱǻȱȱȱȱ§ȱȱȱãǰȱȱ
ȱȱȱȱûȱ ǰȱȱȱȱ ȱȱȱǰȱ ȱãȬ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ Ǽǯȱ ȱ ȱ ȱ ãȱ
ûȱȱǻȱǼȱȱǰȱȱȱȱȱȱȱ£ǯȱȱ
ȱȱãȱǰȱȱȱȱǯ
ȱ
sudoku.in
sudoku.out
1 4 7 5 2 8 9 3 6
***5*8936
8 6 2 7 9 3 1 5 4
*****3*54
9 3 5 4 6 1 2 7 8
9354***78
6 7 9 3 8 2 4 1 5
679*8***5
3 2 4 9 1 5 6 8 7
*******8*
5 1 8 6 7 4 3 9 2
*1**74**2
7 9 1 2 5 6 8 4 3
7**25***3
4 5 6 8 3 9 7 2 1
4*****72*
2 8 3 1 4 7 5 6 9
***1*****
8 1 5 7 3 9 4 2 6
*1***94**
6 7 4 2 8 5 3 9 1
*74***39*
3 9 2 4 1 6 5 8 7
3*****5**
2 8 1 9 5 4 6 7 3
2***5*673
7 5 9 8 6 3 1 4 2
7***63*4*
4 3 6 1 7 2 8 5 9
**6**28**
9 2 3 5 4 1 7 6 8
*********
1 4 7 6 2 8 9 3 5
**7*2**35
5 6 8 3 9 7 2 1 4
568*9**1*
216
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱȱ£§ȱȱȱ£ȱǰȱȱȱȱȱȱȱȱȬ
ȱȱȱȱ ǰȱȱ ȱȱȬȱûȱǻȱûȬ
ȱ£ȱȱȱȱȱȱȱȱȱȱŘǼǯȱȬ
§ȱ§ȱ ȱȱȱDZȱ
•
•
ǽǾǽǾDZȱ£ ȱ¢ȱȱȱ§ȱǻȱ ¡DZȱȬ
ǰȱ£ ȱ ¡DZȱǰȱȱŖȱȱŞȱǼǯȱȱŖȱȬ
ǰȱȱȱȱȱȱûȱǰȱȱãđȱȱȱȱȱǯȱ
ǽǾȱȱǽǾDZȱȱ¢ǰȱȱȱȱȱȱȱȱ
ǻȱƽȱȱǼȱȱȱǻȱƽȱȱǼȱǯ
ȱ
ȱŗDZȱȱȱȱǽŖǾȱƽȱǿřǰȱśǰȱŜǰȱŞǰȱşȀȱ
ȱ ȱ ȱ śȱ ȱ Ş şȱ řȱ Ŝ
ȱŘDZȱȱȱȱǽŗǾȱƽȱǿřǰȱŚǰȱśȀȱ
ȱ ȱ ȱ ȱ ȱ ř ȱ śȱ Ś
ȱřDZȱȱȱȱǽŘǾȱƽȱǿřǰȱŚǰȱśǰȱŝǰȱŞǰȱşȀȱ
şȱ řȱ ś Śȱ ȱ ȱ ȱ ŝȱ Ş
ȱŚDZȱȱȱȱǽřǾȱƽȱǿśǰȱŜǰȱŝǰȱŞǰȱşȀȱ
ȱśDZȱȱȱȱǽŚǾȱƽȱǿŞȀȱ
Ŝȱ ŝȱ ş ȱ Şȱ ȱ ȱ ȱ ś
ȱŜDZȱȱȱȱǽśǾȱƽȱǿŗǰȱŘǰȱŚǰȱŝȀȱ
ȱȱȱȱ ȱ ȱ ȱ ȱ ȱ ȱ Şȱ ȱ
ȱŝDZȱȱȱȱǽŜǾȱƽȱǿŘǰȱřǰȱśǰȱŝȀȱ
ȱ ŗȱ ȱ ȱ ŝȱ Ś ȱ ȱ Ř
ȱŞDZȱȱȱȱǽŝǾȱƽȱǿŘǰȱŚǰȱŝȀȱ
ŝȱ ȱ ȱ Řȱ śȱ ȱ ȱ ȱ ř
ȱşDZȱȱȱȱǽŞǾȱƽȱǿŗȀȱ
Śȱ ȱ ȱ ȱ ȱ ȱ ŝȱ Řȱ ȱ
ȱ
ȱȱȱ ȱ ȱ ŗȱ ȱ ȱ ȱ ȱ ȱ
ȱŗDZȱȱǽŖǾȱƽȱǿŚǰȱŜǰȱŝǰȱşȀȱ
ȱŘDZȱȱǽŗǾȱƽȱǿŗǰȱřǰȱŝȀȱ
ȱřDZȱȱǽřǾȱƽȱǿśǰȱşȀȱ
ȱŚDZȱȱǽřǾȱƽȱǿŗǰȱŘǰȱŚǰȱśȀȱ
ȱśDZȱȱǽŚǾȱƽȱǿśǰȱŝǰȱŞȀȱ
ȱŜDZȱȱǽśǾȱƽȱǿřǰȱŚǰȱŞȀȱ
ȱŝDZȱȱǽŜǾȱƽȱǿŝǰȱşȀȱ
ȱŞDZȱȱǽŝǾȱƽȱǿŘǰȱřǰȱśǰȱŝǰȱŞȀȱ
ȱşDZȱȱǽŞǾȱƽȱǿŘǰȱřǰȱŚǰȱśǰȱŜǰȱŞȀȱ
ȱ
ȱȱ ȱȱȱȱ¢ȱȱûǯȱ
• ǽǾǽǾDZȱ £ ȱ ¢ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
§ȱǻȱƽȱȱǼǯȱ
ȱ
ǻŖǰȱŖǼDZȱȱǽŖǾǽŖǾȱƽȱǿřǰȱȱśǰȱȱşȀȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱDzȱǻŖǰȱŖǼȱƽȱȱȱȱȱȱ
ǻŖǰȱŗǼDZȱȱǽŖǾǽŗǾȱƽȱǿřǰȱȱŚǰȱȱśǰȱȱŞȀȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱDzȱǻŖǰȱŗǼȱƽȱȱȱȱȱȱ
ǻŖǰȱŘǼDZȱȱǽŖǾǽŘǾȱƽȱǿřǰȱȱŚǰȱȱśǰȱȱŜǰȱȱŝǰȱȱŞǰȱȱşȀȱȱȱDzȱǻŖǰȱŘǼȱƽȱȱȱȱȱȱ
ȱ
7
Backtracking
217
ǻŗǰȱŖǼDZȱȱǽŗǾǽŖǾȱƽȱǿŗǰȱȱŜǰȱȱŝǰȱȱşȀȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱDzȱǻŗǰȱŖǼȱƽȱȱȱȱȱȱ ǯȱ
ǻŗǰȱŗǼDZȱȱǽŗǾǽŗǾȱƽȱǿŚǰȱȱŝǰȱȱŞȀȱ
ǻŗǰȱŘǼDZȱȱǽŗǾǽŘǾȱƽȱǿŘǰȱȱśǰȱȱŞȀȱ
ǻŘǰȱŖǼDZȱȱǽŘǾǽŖǾȱƽȱǿŚǰȱȱŝȀȱ
ǻŘǰȱŗǼDZȱȱǽŘǾǽŗǾȱƽȱǿŗǰȱȱŘǰȱȱśȀȱ
ǻŘǰȱŘǼDZȱȱǽŘǾǽŘǾȱƽȱǿŘǰȱȱřǰȱȱŝȀȱ
ȱ
ȱȱȱȱ¢ȱ ȱ §ȱȱȱǯȱ
ȱ
• DZȱȱȱȱ ȱ£ȱȱȱȱȱǯȱ
ȱȱȱȱȱǰȱȱ ȱȱȱȱ£ãȱȱǰȱȱȱ
ȱȱȱ¢ȱȱȱǻȱȱȱȱǻǼǰȱȱ£ȱûǰȱȱȱ
ȱȱȱȱȱȬȱ £ǰȱ ȱȱȬ
ȱȱȱǰȱȱȱȱȱȱȱ§ǼǯȱȱȱȱȬ
ȱ ȱ ȱ Ȭȱ ȱ ȱ ǻȱ ȱ ȱ Ŗȱ Ǽǯȱ ȱ
ȱ £ȱ ȱ şȱ ǻ Ǽȱ ǰȱ ȱ ȱ ȱ ȱ §ȱ ȱ ȱ
ȱŖȱȱǻl++; c=0;Ǽǯ
if (Character.isDigit(ch) || ch == V) {
if (ch != V) {
if (!set(Character.digit(ch, 10)))
return;
}
if (DIM == ++c) {
l++;
c = 0;
}
}
ȱ ȱ ȱ ȱ ǻǼǰȱ ȱ ȱ ȱ ȱ DZȱ
§ȱȱ ȱȱ§ȱȱȱûȱȱǻȱȱȱȱǰȱûȱȱ
ǽǾǽǾȱȱǼǯȱ ȱȱûǰȱȱ ȱȱãȱǯȱȱǰȱȱ ǰȱ
ǽǾǽǾȱ ȱ ȱ ȱ ȱ ŗȱ ȱ şȱ ȱ ȱ ȱ ǻǼȱ £ȱ £ǯȱ ȱ ȱ Ȭ
ȱȱ£ǰȱȱȱȱȱǯȱ
§£ȱ§ȱȱȱȱȱûȱȱȱȱŘȱǰȱȱȱ
ãȱǻȱȱȱȱȱǼȱǰȱȱȱ ȱŘȱȱȱ
£ûȱ ȱ ǻȱ ȱ ȱ ȱ ƽřǼǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ǻȱ ȱ ǯȱ ȱ Ȭȱ ȱ ȱ Ǽǰȱ ȱ ȱ ȱ
ȱȱ ãđȱǯ
218
Grundlegende Algorithmen mit Java
Programm
import java.io.*;
import java.util.*;
public class P13Sudoku {
private static final String FileInputName = "sudoku.in";
private static final String FileOutputName = "sudoku.out";
private static final char V = '*';
private static final int N = 3;
private static final int DIM = N*N;
private BitSet sl[];
private BitSet sc[];
private BitSet[][] sb;
private int[][] v;
private static int anzahl = 0;
P13Sudoku() {
this.sl = new BitSet[DIM];
this.sc = new BitSet[DIM];
for (int i = 0; i < DIM; i++) {
this.sl[i] = new BitSet();
this.sc[i] = new BitSet();
}
this.sb = new BitSet[N][N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sb[i][j] = new BitSet();
this.v = new int[DIM][DIM];
}
boolean set(int l, int c, int value)
{
if (!sl[l].get(value) &&
!sc[c].get(value) &&
!sb[l / N][c / N].get(value))
{
sl[l].set(value);
sc[c].set(value);
sb[l / N][c / N].set(value);
v[l][c] = value;
return true;
}
else
return false;
}
7
Backtracking
void unset(int l, int c, int value)
{
sl[l].clear(value);
sc[c].clear(value);
sb[l/N][c/N].clear(value);
v[l][c] = 0;
}
void run(Scanner scanner, PrintStream out) {
int l = 0, c = 0;
while (scanner.hasNext() && l < DIM) {
String s = scanner.next();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (Character.isDigit(ch) || ch == V) {
if (ch != V) {
if (!set(l, c, Character.digit(ch, 10)))
return;
}
if (DIM == ++c) {
l++;
c = 0;
}
}
}
}
back(0, -1, out);
}
private void writeSolution(PrintStream out)
{
for (int l=0; l < DIM; l++)
{
out.print(v[l][0]);
for (int c=1; c < DIM; c++)
{
out.print(' ');
out.print(v[l][c]);
}
out.println();
}
out.println();
}
private void back(int l, int c, PrintStream out) {
do {
c++;
219
220
Grundlegende Algorithmen mit Java
if (c == DIM) {
c = 0;
l++;
if (l == DIM) {
writeSolution(out);
return;
}
}
}
while (v[l][c] != 0);
for (int value = 1; value <= DIM; ++value) {
if (set(l, c, value)) {
back(l, c, out);
unset(l, c, value);
}
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
scanner = new Scanner(new File(FileInputName));
new P13Sudoku().run(scanner, out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
System.out.print(anzahl);
out.close();
}
}
}
}
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȬǰȱȱȱȱȱȱȱûȱȬ
ȱȱȱȱǻǼȱǻǯȱǯȱȱȱȱȬȱȱǻǼȱȬ
ȱȱȱûȱǽǾǽǾȱȱǰȱȱȱǼȱȱŗȱȬ
ãȱ ǰȱȱȱȱȱȱȱ£§£ȱȱǯȱ
ǯȱ
ȱȱȱŗȱȱ£ȱȱȱ§ȱȱȱȬ
ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ Ȭ
7
Backtracking
řǯ
Śǯ
221
ȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ ȱ ãȱ £ȱ ȱ
ǰȱȱȱȱȬȱ£ȱǻȱȱȱȱ
ȱȱȱȱȱȱȱȱǰȱ ȱȱȱȱ
ǰȱûȱȱȱ ȱȱȱȱãȱǼǯȱ£ȱȱ
£ȱȱȬ ȬȱȱǻǼȱȱȱǰȱȱûȱȱȱȱ
ȱȱȱȱȱǰȱȱȱȱȱȱȬȱȱȬ
ȱ ǰȱ ûȱ ȱ ȱ ȱ ȱ ãđȱ £ȱ ȱ
ȱ ǯȱ ȱ ȱ £ȱ ȱ ȱ ǻǯȱ ȱ ŗǼȱ
ûȱȱûȱȱȱȱǯȱDZȱȱ
ȱ tȱ §ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
ȱ §ǯȱ ȱ tȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ȱȱȱȱ§ȱǮȃȱãȱ£ȱãǰȱȬ
ȱȱȱDZȦȦ
ǯǯǯ.ȱ
ȱȱȱȱȱûȱȱǯȱ
ȱ ǰȱ £ǯȱ ǯȱ DZȦȦ
ǯ¡ǯȦȦ¡ǯȱ ȱ
DZȦȦ
ǯǯȦȦȦȏŖşȏŖśȏŖśǯȱ
§ȱ ȱ ȱ ȱ ǻ£ǯȱ ǯȱ ǰȱ ǰȱ ¡ȱ ǰȱ
ȱ ǰȱ ǯǼǯȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ
ãǯȱȱȱǰȱ ȱãǰȱȱȱȱ£ȱ
ǰȱȱȱȱãȱǯȱ
Problem 14. Das Haus des Nikolaus
ȱ ȱ£ȱȱ ȱǻȱȱȱ
Ǽȱ ȱ ȱ ȱ
4
ǯȱȱȱȱȱ
5
3
££ȱ ȱ ȱ ȱ
ȱ
£ ȱ
£ȱ
ǰȱ ȱ ȱ ȱ
ȱ ǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ
1
2
ȱ ȱ ǰȱ ȱ
ǯȱ
ȱȱȱ ȱȱȱȱǰȱȱȱãȱǰȱ ȱ
ȱȱȱȱȱȱ§ǯȱȱȱ ȱ ȱȱȱ
ȱȱǯȱȱãȱȱ ȱǮŗśřŗŘśŚřŘȄȱ
ǰȱȱȱȱȱȱŗȱǰȱȱȱ£ȱȱśȱ£ǰȱȱ£ȱȱřȱ
ǯǯǯȱ
ȱȱȱ¡ȱȱȱȱãȱȱȱȱ
ȱǯǯȱDZȱ
222
Grundlegende Algorithmen mit Java
ȱ
nikolaus.out
Loesung 1: 1 2 3 1 5 3 4 5 2
.................
Loesung 26: 1 3 5 2 3 4 5 1 2
....................
Loesung 44: 1 5 4 3 5 2 3 1 2
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ ȱ ȱ ûǯȱ ûȱ £ȱ ȱ ȱ ȱ ȱ
ȱ ǯȱ ȱ ££¡ȱ ȱ ȱ
ȱ ȱ
ȱ ȱ
£ ȱ¢ȱǽǾǽǾDZȱȱ
ȱ
­1, wenn eine Kante von i nach j existiert
ǯȱ
aij = ®
¯0, wenn es keine Kante zwischen i und j gibt
ȱ
ȱ ȱ ȱ ãȱ £ȱ ȱ ¢ȱ ǽǾȱ ǰȱ ȱ ȱ ȱ ȱ ûȱ ǽǾȱ Ȭ
ȱ ǰȱȱ ȱȱȱǮ£Ȅȱ ȱǻǽȬŗǾǰȱǽǾǼǯȱȱȱ
ȱȱûȱ ȱȱ ȱ ȱ£ǯȱȱ
Programm
import java.io.*;
public class P14SantaClaus {
private static final String FileOutputName = "nikolaus.out";
private int a[][] = { new int[] { 0, 1, 1, 0, 1 },
new int[] { 1, 0, 1, 0, 1 },
new int[] { 1, 1, 0, 1, 1 },
new int[] { 0, 0, 1, 0, 1 },
new int[] { 1, 1, 1, 1, 0 }
};
private int b[] = new int[9];
private int sol = 0;
private PrintStream out;
P14SantaClaus(PrintStream out) {
this.out = out;
}
7
Backtracking
void run() {
back(1);
}
private void writeSol() {
out.print("Loesung ");
out.print(++sol);
out.print(": ");
for (int i = 0; i < 9; i++) {
out.print(b[i] + 1);
out.print(' ');
}
out.println();
}
void back(int k) {
int i;
if (9 == k) writeSol();
else
for (i = 0; i < 5; i++)
if (a[i][b[k - 1]] == 1 && i != b[k - 1]) {
b[k] = i;
a[i][b[k - 1]] = 0;
a[b[k - 1]][i] = 0;
back(k + 1);
a[i][b[k - 1]] = 1;
a[b[k - 1]][i] = 1;
}
}
public static void main(String[] args) throws IOException {
PrintStream out = new PrintStream(
new File(FileOutputName));
try {
new P14SantaClaus(out).run();
} finally {
out.close();
}
}
}
ȱ
223
224
Grundlegende Algorithmen mit Java
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱûȱȱǯȱ
ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
Ȭȱ ȱ ȱ ȱ £ȱ ǯȱ ȱ ȱ £ ȱ ȱ
ȱȱȱ ȱŚȱȱȱȱȱȱ ȱŗǯȱ
4
7
7
3
5
6
8
4
6
8
1
2
5
9
9
3
1
2
4
10
3
ȱ
1
2
ȱ
ȱ
Noch 10 Probleme
ŗǯ
ȱ ȱ ȱ ȱ Ȭǯȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ãȱ ȱ ȱ đȱ ȱ ȱ ȱ Ȭ
ȱ Ȭǯȱ ȱ ȱ ǻǼǻǼȱ ȱ ǻǻǼǼȱ ȱ ȱ
ȱ ǻǼǼǻȱ ȱ ǼǻǻǼȱ ȱ ǯȱ ȱ £ȱ ȱ ȱ ȱ ãȱ ȱ ȱ
đȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭȱ ȱ
§ 2n ·
ȱ Cn = 1 ¨ ¸ DZȱ
n + 1 ¨© n ¸¹
ȱ
ǻǼǻǼǰȱǻǻǼǼȱ
ǻǼǻǼǻǼȱǰȱȱǻǼǻǻǼǼǰȱǻǻǼǼǻǼǰȱȱǻǻǼǻǼǼǰȱǻǻǻǼǼǼȱ
ŘȱȱÆȱŘȱãȱ
řȱȱÆȱśȱãȱ
ǻǼǻǼǻǼǻǼǰȱǻǼǻǼǻǻǼǼǰȱǻǼǻǻǼǼǻǼǰȱǻǼǻǻǼǻǼǼǰȱǻǼǻǻǻǼǼǼǰȱ
ǻǻǼǼǻǼǻǼǰȱǻǻǼǼǻǻǼǼǰȱǻǻǼǻǼǼǻǼǰǻǻǻǼǼǼǻǼǰȱǻǻǼǻǼǻǼǼǰȱ
ǻǻǼǻǻǼǼǼǰȱǻǻǻǼǼǻǼǼǰȱ
ǻǻǻǼǻǼǼǼǰȱǻǻǻǻǼǼǼǼ
ȱ
ŚȱȱÆȱŗŚȱãȱ
ȱ
ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȬȱǯȱDZȱ
ȱ ȱ ȱ
ȱ
Tastatur
n=3
ȱ
ȱ
()()() ,
klammern.out
()(()), (())(), (()()), ((()))
7
Backtracking
2.
225
§ǯȱȱ£ȱȱ§ȱȱǻŘȱ≤ȱȱ≤ȱŘŖǼȱȱȱ£ãȱ
ȱȱ¡ȱǽǾǽǾȱȱǰȱȱȱǽǾǽǾȱƽȱŗȱǰȱ ȱȱ§ȱȱ
ȱ ȱ ȱ ǰȱ ȱ ǰȱ ȱ ǽǾǽǾȱ ƽȱ Ŗǯȱ ȱ ȱ ȱ ãǰȱ
ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ £§ǰȱ ȱ £ ȱ
§ǰȱ ȱ ȱ £ǰȱ ȱ ȱ ȱ ûǯȱ ȱ
ȱȱȱȱȱȱȱȱȱȱ£ȱȱȱ
ǯȱ ȱȱ£ ȱȱȱȱȱ£ ȱȱûȱȱ
ŗȱȱȱȱȱǯ
karte.in
7
0 1 1 1 0 0 1
1 0 1 1 0 0 0
1 1 0 1 1 0 1
1 1 1 0 1 0 1
0 0 1 1 0 1 1
0 0 0 0 1 0 1
1 0 1 1 1 1 0
řǯ
farben.out
4
1
2
3
4
1
3
2
ȱ
£ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
£ȱ§ǯȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȱ
ȱ ȱ ȱ Ȭȱ ǻŗǰȱ Řǰȱ ǯǯǯǰȱ Ǽȱ ȱ ȱ ∈ȱ ǯȱ ȱ ȱ ȱ ȱ
ŗ×Ř×ǯǯǯ×DZȱ
ȱ
n
∏ A = A × A × ... × A = {(a , a ,..., a ) a ∈ A ∀i = 1,2,..., n} ȱ
i
1
2
n
1
2
n
i
i
i =1
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ£ȱȱȱȱȱ | A1 | ⋅ | A2 | ⋅...⋅ | An | ǯȱ
ȱȱȱ ȱ ȱȱȱ ȱǿŗǰȱŘǰȱǯǯǰȱ ŗȀ×ǿŗǰȱŘǰȱǯǯǯǰȱ
ŘȀ×ǯǯǯ×ǿŗǰȱ Řǰȱ ǯǯǯǰȀȱ ǯȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱǯȱȱȬȱ ȱȱȱȱǯȱȬ
ǰȱȱȱǯȱDZȱ
ȱ
kart.in
kart.out
2 3 1 4
1 1 1 1
1 1 1 2
…
2 3 1 4
ȱ
226
Grundlegende Algorithmen mit Java
Śǯ
śǯ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱ ȱ ȱ ǿ¡ǰȱ ¢ǰȱ £ȱ ∈ȱ Wȱ ȱ Ř¡¢Ƹ¡¢£ƸŚ£ƽŗśŘȀǯȱ ȱ ȱ ȱ
ǯȱ
ȱǯȱȱȱȱǰȱȱȱȱȱDZȱ đǰȱǰȱ
ǰȱǰȱǰȱûȱȱ £ǯȱȱȱȱȱȱȱ
ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ đǰȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ ãȱ ȱ ȱ ǯǰȱ ȱ ȱ
DZȱ
ȱ
flag.out
Gelb Weiss Orange
...
Blau Gelb Rot
...
Weiss Orange Gelbȱ
ȱ
ȱ
Ŝǯ
ȱ
ȱǰȱȱȱȱDZȱȱȱȱȱǵȱ
ȱȱȱȱȱȱǵȱȱȱȱȱȱǰȱȱȱ
ȱ ȱ ȱ ȱ ȱ
ȱ ȱȱȱȱȱȱȬ
ȱȱǯȱȱȱȱ ǰȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ ȱ
ǯȱ
ȱ
ȱ
ûǰȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
ûȱȱȱȱȱȱȱȱȱ ȱǯȱȱȱȬ
ȱ ȱ §ȱ ûȱ ȱ ǯȱ ãȱ ȱ ȱ ȱ ȱ ȱ
Ȭǯȱ
7
Backtracking
227
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ǰȱǰȱȱȱ ȱ
ȱ
228
Grundlegende Algorithmen mit Java
ŝǯ
ȱ ȱ ȱ ȱ ȱ ȱ £ǵȱ ȱ ȱ ȱ ãǰȱ ȱ
ȱ ȱ ȱ ȱ û£ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȱ £ȱ £ǯȱ ȱ ȱ ȱ
¢ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ
û£ȱȱȱ§ȱȱǻŖȱȱ≤ȱȱ≤ȱŗŘŖŖǰȱŗȱȱ≤ȱȱ ≤ȱśŖǼǯȱȱãȱ
ȱȱȱ£ǯȱǯȱDZȱ
ȱ
bezahlen.in
136
12 1 5 25
bezahlen.out
Loesung 1:
136x1
...
Loesung 431:
1x1 + 2x5 + 5x25
ȱ
Şǯ
ȱ¢ǯȱȱ¢ȱȱȱȱ×ȱ¡ȱȱǰȱȱȬ
ȱȱȱǯȱȱ§ȱȱȱŖȱȱȱȱ§£ȱȱŗȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ǰȱ
ȱ ȱ ȱ ȱ ¡ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱȱȱȱȱ ǯȱDZȱ
ȱ
labyrinth.in
4 7
0 0 1 1 0 0 0
0 0 0 1 0 1 0
0 0 X 1 1 1 0
0 1 1 1 0 0 0
labyrinth.out
...
Loesung 3:
0 0 1 4 0 0 0
0 0 0 3 0 1 0
0 0 1 2 1 1 0
0 1 1 1 0 0 0
...
ȱ
şǯ
ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ Ş×ŞȬȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ
ǯȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱǰȱ ȱȱ ȱûȱȱȱûȱǰȱȱȱ
ȱȱǯȱȱǰȱȱȱȱȱȱ £ȱǰȱ
ȱȱ ȱȱŞȱȱǰȱȱȱȱȱ £ǯȱ
ȱ ȱ ȱ £ȱ ȱ £Ȭȱ ȱ ǯȱ DZȱ ȱ
ȱ ǯȱ ȱ ȱ
ȱ ȱ DZȱ Şȱ
ǰȱ ȱ ȱ Şȱ ǰȱ ȱ Şȱ ȱ ȱ ǯȱ ȱ
ȱ ȱ ȱ ȱ ȅǯ′ȱ £ǯȱ ȱ ȱ ȱ ȱ ȅ′ȱȱ
£ǯȱDZȱ ȱȱȱǯȱȱDZȱ
7
Backtracking
ǯ
ǯ
DZȱ
ȱ
229
ȱȱ¡ȱȱȱȱǰȱȱȱȱȱȱ
ȱǮ £ƽȄǰȱȱȱ£ȱȱ £ȱȱȱ
ȱ §ȱ ȱ ȱ ȱ ǮƽȄȱ ȱ ȱ ȱ
£ȱȱDzȱ
ȱȱȱȱȱǰȱǮ ȱǷȄǯȱȱ
bauern.in
bauern.out
Grenzbauern=19
........
Verbandsbauern=21
....BB..
...B....
.BBBBB..
BBBBB...
BBBBB...
..B.B...
.....B..
Kein Verband!
....B...
...B.B..
..B...B.
...B...B
....B.B.
.....B..
........
........
ǻȱȱ Ȭ¢ǰȱ óǰȱ§ǰȱŘŖŖŖǼȱ
ȱ
ŗŖǯ ȱǯȱȱȱȱûȱȱŗǰȱŘǰȱdzǰȱȱǻŗȱ≤ȱȱ≤ȱřŖǼȱǰȱ
ȱ¡ȱşȱȱȱǯȱȱ ȱǰȱȱ ȱ¢ȱ
ȱȱȱȱǰȱȱ ȱǰȱȱȱȱ¢ȱȱȱ
£ ȱŘȱȱŗŖȱȱȱǯȱȱȱûȱȱȱ¡ȱȱ
¢ȱȱȱǰȱȱȱȱȱ ȱȱ§ȱǰȱ
ȱȱȱȱ£ȱ ȱȱǯȱDZȱȱȬ
£ȱ ŗǰȱ Řǰȱ dzǰȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ǯǯȱ
DZȱ ȱǯȱȱȱȱȱȱȱǻǰȱǼȱȱȱ£Ȭ
ȱȱȱȱ ǰȱ ȱȱǯȱ ȱȱ£ȱȱȱ
ȱȱȱ ȱǯȱDZȱ
ȱ
basis.in
basis.out
12102 34215
1231 1010101
343421
2314
23413
28756
28457
n
Basis(n)
12102
6
34215
6
2314
9
28756
9
1231
10
n Dezimal
1766
4835
1714
19572
1231
230
Grundlegende Algorithmen mit Java
1010101
4
4369
23413
5
1733
28457
9
19330
343421
5
12361
Intervall: [1231,19572]
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱȱ Ȭ¢ǰȱóǰȱ§ǰȱŗşşŝǰȱ£Ǽȱ
ȱ
DZȱȱãȱȱȱȬȱ£ǰȱ£ǯȱǯDZȱ
void back(int k){
if(k==n)
processThisCombination();
else
for(int i=base[k];
i<=10; i++)
{
x[k]=i;
back(k+1);
}
}
ȱ
ȱ
ȱ
ȱȱȱ
• ȱ Ȭ ȱ ȱ
ȱǻƽǼǰȱȱûȱ ǰȱȱȱ
£ãȱ ȱ ȱ ȱ ȱ
ȱȱǯȱȱ
• ȱ ȱ Ȭ ȱ Ȭ
ȱ ȱ ǻǀǼǰȱ ȱ £ȱ ¡ǽǾȱ
ȱ ȱ ãȱ ȱ ûȱȱ Ȭȱ
ȱ ǻȱ ȱ ȱ ǽǾǼȱ ȱ
ȱ ûȱ ȱ ȱ ȱ ȱ ûȱ
Ƹŗȱǯȱ
ȱ
£ȱȱȱȱȱȱ ȱȱǰȱȱ
ȱ
Dynamische Programmierung
8
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
Grundlagen, Eigenschaften des Verfahrens
1. Ursprung des Konzeptes.ȱ ȱ ¢Ȭ
ȱȱȱȱȬ
ȱ ǰȱ ȱ Ȭ
ȱ £ȱ ãǯȱ ȱ ȱ
ȱ ȱ ȱ ŗşŚŖȱ ȱ Ȭ
ȱ ȱ ȱ ȱ
ǻŗşŘŖȮŗşŞŚǼȱǯȱȱ ȱȱȱ
ȱ ǰȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ £ȱ ȱ ¢ȱ Ȭ
ǯȱ
ȱ
Richard Bellman
2. Optimalitätsprinzip.ȱ
ĸ ȱ ¢ȱǰȱȱȱ
ȱ ¢ȱ ȱ Ȭ
ȱȱȱȱŗşŝşȱ ȱ ȱȱȱ
ȱ ȱ ȱ §£ǯȱ ȱ
DZȦȦ
ǯǯȦ£Ȧȱ
đǰȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¢ȏȦȦǯȱ
£ȱ ȱȱȱȱȱ
ãȱ ȱ ȱ ȱ
ȱãǰȱȱȱȱãȱȱȱ£ȱǯȱȱȬ
§£ȱȱȱûȱȱǯȱȱ
ȱȱȱǰȱȱ ȱȱȱȱ£ ȱȱ ȱȱȱ
ȱȱ ȱȱ ǯȱȱȱ£ȱǰȱȱ ȱȱȱȱ
ȱ §ȱ £ ȱ ȱ ȱ ȱ ȱ ȱ đȱ ǯȱ ȱ ȱ
ǰȱȱȱȱȱȱȱ§ȱȱ£ȱ ȱȱǰȱȱȬ
ȱȱ£ ȱȱȱǯȱȱȱȱȱȱ£ ȱȱȱȬ
ȱȱȱȱȱȱȱȱǯȱȱ
ȱ
232
Grundlegende Algorithmen mit Java
ŘŗŚ
řş
ŘŜŞ
i
ŗś
j
dz
ŘŗŖ
Śŗ
ȱȱȱȱ£ ȱ£ ȱ ȱȱ ȱ
ȱ
ȱ ȱ ȱ ãȱ ȱ ȱ ȱ §£ȱ ȱ Ȭ
ȱDZȱ
ȱ
ŗǯ ȱȱȱȱȱȱ
Řǯ ȱãȱȱȱȱȱȱřȬȬȱ
řǯ
ȱȱȱãȱȱǰȱȱȱȱãȱ
ȱȱ£ȱȱ
ȱ
3. Überlappung der Probleme, Speicherung der optimalen Teilproblemlösungen (Memoization).ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ tȬ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãǯȱ
tȱǰȱȱȱȱãȱȱȱ£ȱȱ
ȱãȱǰȱȱȱȱ ȱǯȱȬ
£ȱǰȱȱȱãȱȱȱûȱȱ§ȱȱ
ȱ ǰȱȱȱ£ȱ£ȱǯȱ
ȱ
4. Einführendes Beispiel – die Fibonacci-Folge.ȱȱȱȱǰȱȱ
ȱȱȬȱ£ȱǯȱȱȱ ȱȱDZȱȱ
ȱ
• ǻŖǼȱƽȱŖǰȱǻŗǼȱƽȱŗȱȱ
ȱ
ȱ
ȱ
• ǻǼȱƽȱǻȬŗǼȱƸȱǻȬŘǼȱûȱȱȱ≥ȱŘȱ
ȱ
ȱ
ȱ
ȱȱǻŗǼ
ȱ
ȱ
ȱ
ȱ
ȱǻśǼȱȱȱȬȱ£ȱǰȱȱ ȱȱȱǻŚǼȱȱǻřǼǯȱ
DZȱȱȱȱȱȱǻǼȱ£ȱǰȱȱȱǻȬŗǼȱȱǻȬŘǼǯȱ
ȱȱȱ§ȱȱȱ §ǰȱ£ǯȱǯȱȱȱȬ
ȱǰȱûȱȱȱȱȱ ǯȱȱ ȱǻśǼDZȱȱ
ȱ
ȱ
8 Dynamische Programmierung
233
ȱȱȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱ ȱ
ǻśǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŚǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻřǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻřǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŘǼȱȱȱȱȱȱȱȱȱǻŘǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŗǼȱ
ȱ
ǻŖǼ
ǻŗǼ
ǻŘǼ
ǻřǼ
ǻŚǼ
ǻśǼ
ǻŘǼȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻŗǼȱȱȱȱǻŗǼȱȱȱȱȱȱȱǻŖǼȱȱȱȱȱȱȱȱǻŗǼȱȱȱȱǻŖǼȱ
ȱ
ǻŗǼȱ
ȱȱǻŖǼȱ
ȱȱǻśǼDZȱȱȱȱȱ£¢ȱ ȱǻǯȱȬ
ȱ¢ȱǰȱ Ǽȱ
ȱ
ȱ ȱ ȱ §ȱ ǻŘǼȱ ȱ ȱ ȱ ǻřǼȱ £ ǯȱ ȱ ȱ Ȭ
ȱȱȱȱȱȱȱǻŘǼǰȱǻřǼǰȱǻŚǼǰȱǯǯǯǰȱǻǼǰȱȱȱȬ
ȱ ȱ ȱ ãȱ ȱ ȱ ǯȱ ȱ ãȱ ȱ ȱ
ȱ£ȱ DZȱ
ȱ
ȱȱȱȱ£ȱȱȱȬȱ
ȱ
ȱȱȱȬȱȬ
Ȭȱȱ
ȏǻǼȱ
ȱȱȱ ȱǻƽƽŖȱȱȱȱƽƽŗǼȱȱȱ
ȱȱȱȱȱȱȱȱ
ȱȱȱȏ ȱ
ȱȱȱȱ¡ȱ
ȱȱȱȱȱȱȱǻȬŗǼƸǻȬŘǼȱ
ȱȱȱȏȱ
ȏȱ ȏȱǻǼ
ȱȱȱȬȱȬ
ȱǻ¢ȱǼȱ
ȏ ǻǼȱ
ȱȱȱǽŖǾȱ←ȱŖȱ
ȱȱȱǽŗǾȱ←ȱŗȱ
ȱȱȱȱǻȱƽŘDzȱ≤DzȱȱŗȱǼȱ¡ȱ
ȱȱȱȱȱǽǾȱȱ←ȱǽȬŗǾȱƸȱǽȬŘǾȱ
ȱȱȱȏȱ
ȱȱȱȱǽǾȱ
ȏȱ ȏ ǻǼȱ
ȱ
ȱ
ȱ
ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
£ȱȱȱDZȱ
ȱ
ȱ
ȱ
ȱ
ȱ
234
Grundlegende Algorithmen mit Java
ȱȱ£ȱûȱȱȱȱȱȱ
ȱ
N
F(n)
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
Laufzeit
rekursiver
Fibonacci
Laufzeit
iterativer
Fibonacci
3
5
7
11
18
30
46
76
122
198
320
522
845
1361
2211
3710
5904
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
<1
ȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ûȱ ȱ ȱ ȱ ȱ
ȱ §ǰȱ ȱ§ȱȱȱ§ȱ ȱ ǯȱȱ ¡§ȱ
·
§
ȱȱȱ¡DZȱ O¨ §¨ 5 + 1 ·¸ ¸ ǯȱȱ£ ȱȱ ȱȱ
n
¨¨ ¨
©©
2
¸ ¸¸
¹ ¹
§£ǯȱ ȱȱ ȱȱȱȱȱȱȱȱȱȬ
ȱǰȱȱȱ§ȱ ȱȱ£ȱãǯȱȱ ¡§ȱȬ
ûȱȱDZȱǻǼǯȱȱȱȱȱȱŗȱȱȱȬȱ£ûǯȱ
ȱ
5. Bottom-up versus top-down.ȱ ȱȱȱȱȱ¢ȱ
ȱȱȱȱȱ§£DZȱ
ȬȬ£DZȱ ȱ ǰȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ
ȱ ãǯȱ ȱ ȱ ȱ ãȱ £ǰȱ ȱ ȱ ãȱ ûȱ
ãđȱ ȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ ãȱ ûǰȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ǯȱ
DZȱǻǼȱȱ£ȱ ǰȱȱȱǯȱ
Ȭ Ȭ£DZȱ ȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ ȱ Ȭ
ȱ ȱ ãȱ ȱ ȱ ãȱ ûȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ȱ ǯȱȱȱ ȱȱȱȱȱãǯȱȱ
ȱ
6. Vergleich mit anderen Verfahren.ȱ ȱ ȱ ȱ ȬȬ Ȭ
ǰȱ ȱȱȱȱ§ȱ ȱȱ ûǰȱ ȱȱ
8 Dynamische Programmierung
235
ȱ ȱ ¢ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱȱȱǯȱȱȬ
ȱȱȱȱãȱȱȱãȱȱ ǰȱȱ£ȱȱ§Ȭ
ȱȱȱ£ûȱ£ȱãǰȱȱȱȱȱ£ȱûȱ
ǻ£Ǽǯȱȱ
ȱ
ȱ ȱ ȱ ¢ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ £ǯǯȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ £ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ Ȭ
ȱȱȱtǰȱȱȱ£ȱȱȱȱ ȱ
ǯȱ
ȱ
ȱȱȱãȱȱ ǰȱȱȱãȱ§ȱ£ȱûȬ
ǰȱ ȱ ȱ ȱ ȱ ¢Ȭǯȱ ȱ ȱ ȱ ǰȱ
ȱȱ ¢Ȭȱȱȱȱ£ȱȱȱȱ §ȱ
ȱȱ¢ȱȱȱ§£ȱ£ǯȱȱ
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
ȱ ȱ ȱ ȱ §£ǰȱ tȱ ȱ ǰȱ
£ǯȱȱ
ȱȱȱ ȱȱ¢ȱǵȱ
ȱ ȱ ¢ȱ ȱ ûȱ ȱ ȱ ȱ ¢ȱ Ȭ
ȱȱȱȱȱ£DZȱ
§n·
¨¨ ¸¸ = 1, ȱ ȱȱƽȱŖȱȱȱƽȱ
©k ¹
§ n · § n − 1· § n − 1·
¸¸ ǰȱȱǁȱǰȱȱȱ≠ȱŖȱ
¸¸ + ¨¨
¨¨ ¸¸ = ¨¨
© k ¹ © k − 1¹ © k ¹
ȱ
ǻŘǼȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ǰȱ £¢Ȭ
§ 4·
© 2¹
ȱ ȱ ûȱ ȱ ȱ ȱ ¨¨ ¸¸ ǰȱ ȱ ȱ ȱ Ȭ
ȱȱǻśǼǯȱ
236
Grundlegende Algorithmen mit Java
Problem 1. Das Zählen der Kaninchen
ǯȱ ŗŗŞŖȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭ
ȱ ǰȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ §ȱ ǰȱ ȱ ȱ
ȱ Ȭȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱ Ȉȱ Ȉȱ ǻȱ ȱ Ǽǰȱ ȱ ȱ ȱ ȱ
ȱ ȱ Ȭȱ ȱ û ȱ
ȱ ȱ ȱ ȱ ǰȱ
ȱ §ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ǰȱȱ£ǯȱǯDZȱ
ȱ
ȱ £ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
ȱ ȱǰȱ ȱȱǰȱȱȱȱȱȱȱ ȱȱ£ǰȱ
ȱȱ ȱȱȱȱȱ£ ȱȱȱǵȱ
ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱǰȱȱ ȱȱȱȱȱȱȱDZȱŖƽŖǰȱŗƽŗȱȱ
ȱƸŗƽƸȬŗǯȱȱȱȬȱȱDZȱŖǰȱŗǰȱŗǰȱŘǰȱřǰȱśǰȱŞǰȱŗřǰȱŘŗǰȱřŚǰȱśśǰȱ
ŞşǰȱŗŚŚǰȱŘřřǰȱřŝŝǰǯǯǯȱ
ȱ
ȱȱȱǰȱȱȱ ȱȱȱȱȱȱȬ
ȱȱȱśŖȱȬȱǰȱȱȱȱȱ£ȱûȱȱ
ȱȱȱDZȱ
ȱ
N
FibRec(N) Zeit(FibRec(N))
FibIt(N) Zeit(FibIt(N))
..........
33
3524578
t1=
2
3524578
t2=
0
34
5702887
t1=
3
5702887
t2=
0
35
9227465
t1=
4
9227465
t2=
0
36
14930352
t1=
7
14930352
t2=
0
37
24157817
t1=
11
24157817
t2=
0
..........
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱȱȱŗǻǼȱȱŘǻǼȱǰȱȱȱȱȬ
ǯȱȱȱȱȱ§ȱȱȱȬǯȱ
ȱ £ ȱ ȱ ȱ ¢ȱ ȱ ȱ ǰȱ ȱ ûȱ ȱ ȱ ȱ ǽǾȱ ȱ ȱ
ȱȱǽȬŗǾȱȱǽȬŘǾȱ£ǯȱȱȱȱ ȱȱȱȬ
8 Dynamische Programmierung
237
ȱ ¢ǯǻǼȱ ȱ ȱ ȱ ǯǯȱ ȱ ȱ ǰȱ
ȱȱȱȱŗǯŗǯŗşŝŖǰȱŖŖDZŖŖȱǰȱȱ£ȱȱȱȱ
ǰȱȱȱȱȱȱȱȱȱ¢ȱȱ£ûDZȱ
ȱ
public static long currentTimeMillis ()
Programm
import java.io.*;
public class P01Fibo {
private static final String
FileOutputName = "FiboReport.txt";
private static final int N = 50;
private static long fibo1(int n) {
if (n <= 1)
return n;
return fibo1(n - 1) + fibo1(n - 2);
}
private static long fibo2(int n) {
if (n < 2) {
return n;
}
long prevprev = 0;
long prev = 1;
for (int i = 2; i < n; i++) {
long temp = prev;
prev += prevprev;
prevprev = temp;
}
return prev + prevprev;
}
public static void main(String[] args) throws IOException {
PrintStream out = new PrintStream(
new File(FileOutputName));
try {
for (int i = 0; i < N; i++) {
long tm = System.currentTimeMillis();
long f = fibo1(i);
tm = System.currentTimeMillis() - tm;
out.printf("%4d %15d
t1=%6d", i, f,
238
Grundlegende Algorithmen mit Java
Math.round(tm / 1000));
tm = System.currentTimeMillis();
f = fibo2(i);
tm = System.currentTimeMillis() - tm;
out.printf(" %15d
t2=%6d%n", f,
Math.round(tm / 1000));
out.flush();
}
} finally {
out.close();
}
}
}
Aufgaben
ŗǯ
ȱ
Řǯ
ȱȱŖƽŘǰȱŗƽŗȱȱƽȬŗƸȬŘȱȱȱđȱȬǯȱ
ȱ ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ Ȭȱ
ûǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ Ȭȱ ȱ
Ȭȱȱȱȱȱ£ȱǯȱ
ȱȱȬȱȱȱȬȱȱȱȱ§Ȭ
ȱ ȱ £ǯȱ ǯȱ ŘƸŘȉǻȬŗǼȬŗȱ ƽȱ śŘǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱûȱȱƽȱŖǰȱŗǰȱŘǰȱǯǯǯǰȱŘśȱûȱȱȱȱǰȱ£ǯȱǯȱȱDZȱ
n
L(2n)+2(-1)^(n-1)
5F(n)^2
__________________________________________
0
0
0 OK!
1
5
5 OK!
2
5
5 OK!
..........
22
1568397605
1568397605 OK!
23
4106118245
4106118245 OK!
24
10749957120
10749957120 OK!
25
28143753125
28143753125 OK!
ȱ
řǯ
ȱ ȱ ŖƽŖǰȱ ŗƽŗǰȱ ŘƽŘȱ ǻȱ řƽŚǼȱ ȱ ƽ ȬŗƸ ȬŘƸ ȬřǻƸ ȬŚǼȱ ȱ
ȱđȱȬȱǻȬǼǯȱȱȱûȱȱȬ
ȱ ƽŘȬŗȱ ûȱȱǁȱŖȱȱ Ŗȱ ƽȱŖǯȱȱȱȱȱȱǰȱ
ȱȱȬȬȱȱ£ȱȱȱȱDZȱȱ
ȱ
ƽŖǰȱ ŗƽŗǰȱǯǯǯǰȱ ȬŗƽŘȬŗȱȱ
ȱƽȱ ȬŗȱƸȱ ȬŘƸǯǯǯƸ Ȭȱûȱȱ≥ȱȱ
Ŗ
ȱ
8 Dynamische Programmierung
239
£ȱȱȱǰȱȱûȱûȱȱȱȱȱȱ ȱȬ
ǰȱȱȱȱȱǯȱ£ȱȱûȱȱȱȱ¢Ȭ
ȱǯȱDZȱ
ȱ
kBonacci.in
kBonacci.out
3 50
n
kBonacci(3, n)
__________________________
0
0
1
1
2
2
3
3
4
6
...
47
1424681173049
48
2620397211992
49
4819661885417
50
8864740270458
5 57
n
kBonacci(5, n)
__________________________
0
0
1
1
2
2
3
4
4
8
5
15
...
55 7280158119874827
56 14312414018268228
57 28137465101354548
ȱ
Śǯ
ȱȱȱȱȱȱȱȱȱȱȱȬ
£ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ đȱ ȱ ȱ
ǻ ȱǯǯ Ǽǯȱ
ȱȱ ȱȱ¢ȱȱȱȱȱ
§n·
©k ¹
ȱ£ȱ ¨¨ ¸¸ ǰȱȱȱȱȱȱȱǻŘǼȱȱǯȱ
ȱ ȱȱȱȱ ȱ£ȱȱȱȱ
ǯȱȱȱ£ȱûǰȱȱȱȱȱȱȱȱ
ȱ ȱ £ȱ ûȱ ȱ ȱ £ǯȱ £ȱ ȱ ȱ ȱ
ȱ ǯǰȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ £ȱ ȱ
ȱȱȱȱãȱȱȱ ǯȱȱûȱȱƽȱřDZȱȱ
ȱ
ȱ
240
Grundlegende Algorithmen mit Java
0
1
2
3
1
1
1
1
1
2
3
1
3
1
Problem 2. Längste aufsteigende Teilfolge
ȱȱ ȱȱ ȱǽŖŘǾǰȱȱŗśŚǰȱȱȱȱȱæȱȱ
£DZȱ
£ȱ ǻĘǰȱ £Ǽǯȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ Ƹŗȱ ȱ Ƹŗȱ ȱ ȱ
ȱȱȱȱȱȱȱȱ
ai1 < ai2 < ... < aim+1 ȱȱȱȱǻŗȱǀȱŘȱǀȱdzȱǀƸŗǼȱ
ȱ§ȱƸŗȱȱȱȱȱ
a j1 > a j 2 > ... > a j n +1 ȱȱȱǻŗȱǀȱŘȱǀȱdzȱǀƸŗǼȱ
ȱ §ȱ Ƹŗȱ ȱ ǯȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
£ȱȱȱȱǽŖŘǾȱ£ȱǯ÷ȱ
ȱ
ȱȱȱȱȱȱ§ȱȱȱȱȱȱ
ȱȱ ǯȱDZȱ ȱȱȱǯȱȱȱȱȱȬ
ûȱ ǯȱ ȱ £ȱ ȱ ȱ §ȱ ãȱ ŘŖŖŖǰȱ ȱ ȱ ȱ ȱ
ŘŖǯŖŖŖǯȱ DZȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ§ȱȱȱǯȱDZȱ
aufsteigend.in
aufsteigend.out
3 5 76 1 45 2 31 89 90
0 4 15 23 47 95 21 67
8 13 11 5 145 132 77
--- Eingabe:
Laenge: 24
Die Elemente: 3 5 76 1 45 2 31 89 90 0 4
15 23 47 95 21 67 8 13 11 5 145 132 77
--- Ausgabe:
Laengste aufsteigende Teilfolge: 1 2 4
15 23 47 95 145
Laenge: 8
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱȱǽǾȱȱȱȱȱȱȱȱǽǾȱȱ
ǽǾȱDZȱ
ȱ
ǽŖǾȱ←ȱŗǰȱȱ
ǽǾȱ←ȱŗȱƸȱ¡ǿǽǾȱȱȱǀȱȱȱȱȱǽǾȱǀȱǽǾȀǰȱȱƽȱŗǰȱdzǰȱȬŗȱ
8 Dynamische Programmierung
241
ȱ
ȱȱȱ
ȱ
ǽŖǾȱȱ←ȱȬŗȱȱǻȱȱȱȱȱ§Ǽȱ
ȱȱ¡ȱȱȱǽ¡Ǿȱƽȱ¡ǿǽǾȱǀȱȱǽǾȱǀȱǽǾȀȱǰȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱ£ȱǽǾȱƽȱ¡Dzȱ
ȱǽǾȱƽȱȬŗȱǻȱȱȱ§Ǽǯȱ
ǽǾȱȱȱ§ȱȱ¡ȱǰȱȱȱǽǾȱȱ£ȱȱ
ǯȱDZȱȱȱȱŗǰȱŘǰȱǯǯǯǰȱȱǯȱȱȱ§ȱȱȬ
ȱȱǰȱȱȱȱȱ£ȱȱȱȱȱǯȱ
ȱ
ǽǾȱȱȱ ¡ȱȱ§ȱȱȱȱȱȱ§ȱȬ
ȱȱȱȱ£ȱǯȱȱȱǰȱȱ§ȱȱȱȱ
ȱȱǻǼȱ£ǯȱȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯǰȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ tǯȱ ȱ ȱ ǯȱ ǻȱ
ȦȬ§ǼȱȱȱȱȱŗǯŚǯȱȱ ȱ£ǯȱȱȱ Ȭ
ȱ DZȱ ǰȱ ¢ǰȱ ǰȱ ǰȱ ǰȱ ǰȱ ǰȱ
ǯȱȱȱȱȱǰȱȱȱ£ȱȱȱȱȬ
ȱ¢ȱ§ǯȱȱȱȱȱ ȱȱȱȱǻǼȱȱ
ǻǼȱ ȱ ȱ ȱ ȱ £ ǯȱ ȱ ȱ ǯȱ ȱ ȱ §ȱ
ȱ ãȱ ȱ £ ȱ ȱ Ȭȱ ȱ Ȭ
ȱ ȦȬ§ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ Ȭǯȱ ȱ ȦȬ
ȱ ȱȱǻǼȱȱ ǻǼȱȱȱȱȱûǯȱ
ȱ
ȱ ȱŖŘǻǀ ǁǼȱȱȱȱȱȱȱȱ
ȱ ȱ ȱ ȱ Ȭȱ ȱ ȱ ȱ ȱ ¡ȱ §ȱ
ǯ£ǻǼǯȱ
ȱ
Programm
import java.io.*;
import java.nio.*;
import java.util.*;
public class P02Ascending {
private static final String FileInputName = "aufsteigend.in";
private static final String FileOutputName =
"aufsteigend.out";
private List<Integer> a;
private IntBuffer v, vPred;
242
Grundlegende Algorithmen mit Java
private int imax;
P02Ascending(List<Integer> list) {
this.a = list;
this.v = IntBuffer.allocate(list.size());
this.vPred = IntBuffer.allocate(list.size());
}
void process() {
int j, i, n;
v.put(1);
vPred.put(-1);
this.imax = 0;
n = (int) a.size();
for (i = 1; i < n; i++) {
v.put(1);
vPred.put(-1);
for (j = 0; j < i; j++)
if (a.get(j) < a.get(i) && v.get(j) + 1 > v.get(i)) {
v.put(v.position() - 1, v.get(j) + 1);
vPred.put(vPred.position() - 1, j);
}
if (v.get(i) > v.get(imax))
this.imax = i;
}
}
private void recoverSubstring(int i, PrintStream out) {
if (vPred.get(i) + 1 != 0)
recoverSubstring(vPred.get(i), out);
out.print(a.get(i));
out.print(' ');
}
void writeData(PrintStream out) {
ȱ ȱ ȱ ǮȬȃǰȱ ȱ
out.println("--- Eingabe: ");
ȱ ȱ ȱ śȱ ûȱ ǰȱ ȱ
out.print("Laenge: ");
ȱ ȱ ȱ ȱ ȱ
out.println(a.size());
ǮforȃDZȱ
out.print("Die Elemente: ");
for (Integer i : a)ȱ
for (Integer i : a) {
ȱDZȱ
out.print(i);
for(type iterVar:iterableObj)
out.print(' ');
Anweisung;
}
out.println();
out.println("--- Ausgabe: ");
out.print(" Laengste aufsteigende Teilfolge: ");
recoverSubstring(imax, out);
out.println();
8 Dynamische Programmierung
243
out.print(" Laenge: ");
out.println(v.get(this.imax));
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
out = new PrintStream(new File(FileOutputName));
scanner = new Scanner(new File(FileInputName));
List<Integer> list = new ArrayList<Integer>();
while (scanner.hasNextInt()) {
list.add(scanner.nextInt());
}
P02Ascending p = new P02Ascending(list);
p.process();
p.writeData(out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱ
£ȱȱȱȱǰȱȱȱûȱȱȱȱ¢ȱ Ȭ
ǯȱ
ȱ ȱ ȱ Ȭ Ȭȱ ûȱ ȱ ȱ ȱ ȱ Ȭ
ǯǯ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ£ǯȱȱ
ȱãȱȱȱǰȱȱȱ¡ȱ§ȱǯȱ ȱ
ȱȱȱȱǰȱȱȱȱȱ¡ȱ§ȱȬ
ȱǯȱ
ȱȱȱȱǰȱȱȱȱ§ȱȱȱ
ȱ DZȱ
244
Grundlegende Algorithmen mit Java
teilfolge.in
teilfolge.out
3 5 76 1 45
2 31 89 90 0
4 15 23 47
95 21 67 8
13 11 5 145
132 77 -1 -2
57
--- Eingabe:
Laenge: 24
Die Elemente: 3 5 76 1 45 2 31 89 90 0 4 15
23 47 95 21 67 8 13 11 5 145 132 77
--- Ausgabe:
Laengste aufsteigende Teilfolge : 1 2 4 15
23 47 95 145
Length: 8
--Laengste absteigende Teilfolge : 76 45 31
23 21 13 11 5 -1 -2
Length: 10
ȱ
śǯ
Ŝǯ
ȱȱȱȱǰȱȱȱ£ȱȱæȱȱ£ȱûȱ
ȱ§£ȱûǯȱȱȱ ȱȱȱDZȱȱûȱȬ
ȱ ȱ£§ȱDzȱȱȱûȱȱǰȱȱȱȱǂȱȱȱȱƽȱƸŗȱ
ȱ §ȱ ȱ ȱ ȱ §ȱ ȱ ǯȱ £ȱ
ȱȱȱǯȱ
ȱ ãǯȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ¡ǰȱ ȱ ȱ
ãȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ££ȱ
ǯȱȱȱȱǰȱȱȱ§ȱȱȱãȱȱ
ȱ¡ȱǰȱûȱȱǰȱȱȱȱ£ȱȱȱȱ
ȱȱȱȱȱȱ§ȱȱûǯȱ
DZȱ ȱȱȱ ǯȱȱȱãȱǻȱȱ¡ȱŗśȱȱ
ȱŘȱȱǼǰȱȱȱ£ȱȱȱǻȬ
Ǽȱȱǯȱ
DZȱ ǯȱȱȱȱǯȱ ȱȱȱȱȱȱ
£ȱ ȱ ãȱ ȱ §ȱ ǰȱ ȱ ȱ §ȱ ȱ ȱ ȱ
ãȱȱǰȱȱȱǯȱDZȱ
ȱ
woerter.in
griul
visului
ultim
cazu
imprecis in
clipa
aceea de isterie
iesita parca din
tainite vechi si tenebroase
woerter.out
7
griul
ultim
imprecis
isterie
iesita
tainite
tenebroase
8 Dynamische Programmierung
245
Problem 3. Längste gemeinsame Teilfolge (LCS)
ȱ ȱ ȱ §ȱ ȱ ȱ ǻǯȱ ȱ ȱ Ȭ
Ǽȱȱȱȱȱȱ¢ȱǯȱȱ
ȱŗǯȱȱȱȱƽȱǻ¡ŗǰȱ¡Řǰȱǯǯǯǰȱ¡Ǽȱȱȱƽȱǻ£ŗǰȱ£Řǰȱǯǯǯǰȱ£Ǽȱ£ ȱȱȱȱ£ ǯȱȱ
ǰȱ ȱǰȱȱzWǰȱǰȱȱ≥ȱŗȱȱȱ≥ȱȱǯȱȱȱȱȱȱȱǰȱ
ȱȱȱȱ ¡ȱŗǰȱŘǰȱdzǰȱȱǰȱȱȱûȱȱƽŗǰȱǯǯǯǰȱȱǯȱȱ
DZȱûȱƽǿŗŖǰȱŚǰȱŘŖǰȱŗŖǰȱŚŖǰȱŘǰȱŖǰȱŜŖȀȱȱƽǿŚǰȱŗŖǰȱŘǰȱŖȀȱȱȱȱ§ȱŚǯȱ
ƽǿŚǰȱŗŖǰȱŘǰȱŚŖȀȱȱȱȱȱǯȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱ ȱȱǯȱȱđǰȱȱȱȱȱȱȱ
ȱȱȱ ȱǯȱȱȱȱȱȱûȱȱ
ȱ§ǯȱȱ
ȱȱ§ȱȱǯȱ ȱȱ£ ȱȱȱƽȱǻ¡ŗǰȱ¡Řǰȱ
ǯǯǯǰȱ¡Ǽȱȱȱƽȱǻ¢ŗǰȱ¢Řǰȱǯǯǯǰȱ¢Ǽȱȱŗ≤ȱǰȱȱ≤śŖŖǯȱ ȱȱȱ§ȱȱǰȱȱȬ
ȱȱȱȱȱȱȱȱǯȱȱ
DZȱûȱƽǿŗŖǰȱŚǰȱŘŖǰȱŗŖǰȱŚŖǰȱŘǰȱŖǰȱŜŖȀȱȱƽǿŚǰȱşŖǰȱŝǰȱŗŖǰȱŝŖǰȱŘǰȱŝŗǰȱŞŗǰȱŖȀȱȱƽǿŚǰȱŗŖǰȱ
ŘǰȱŖȀȱȱȱ§ȱŚȱȱ§ȱȱǯȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ
£ȱȱȱȱȱȱȱȱȱȱȱ ȱȱȱ
£ȱȱȱȱȱȱǯȱȱȱȱȱ¢ȱǯȱDZȱ Ȭ
ȱȱȱȱȱǯȱȱ§ȱȱȱǯȱDZȱ
ȱ
lcs.in
lcs.out
8 9
Maximale Laenge: 4
4 10 2 0
10 4 20 10 40 2 0 60
4 90 7 10 70 2 71 81 0
14 22
Maximale Laenge: 8
34 67 8 0 12 3
45
91
34 5 67 8 8 9 0 12 3 45 6 78 91
231
12 34 45 67 79 57 8 321 55 0 33
12 1 2 3 44 45 56 91 21 22 23
Problemanalyse und Entwurf der Lösung
ȱȱȱ£ȱȱ ȱȱ§ȱǻǼȱȱȱȱƽȱǿ¡ŗǰȱ¡Řǰȱ
dzǰȱ¡Ȁȱȱȱƽȱǿ¢ŗǰȱ¢Řǰȱdzǰȱ¢ȀȱȱŖ≤ȱȱ≤ȱǰȱŖȱ≤ȱȱ≤ȱȱȱǽǾǽǾȱǯȱȱ¡ȱƽȱ¢ȱǰȱȱŗƸǽȬ
ŗǾǽȬŗǾȱȱ§ȱȱ§ȱȱǻǼǯȱȱ¡ȱƾȱ¢ȱǰȱȱȱȬ
246
Grundlegende Algorithmen mit Java
¡ȱ ȱ ǽȬŗǾǽǾȱ ȱ ǽǾǽȬŗǾȱ ȱ §ȱ ȱ §ȱ ȱ ǻǼǯȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ǽǾǽǾȱ ǰȱ ȱ ûȱ ǰȱ ȱ
ȱȱDZ
ȏȱǻȱƽȱǿ¡ŗǰȱ¡Řǰȱdzǰȱ¡Ȁǰȱȱƽȱǿ¢ŗǰȱ¢Řǰȱdzǰȱ¢ȀǼȱ
ȱȱȱ
ȱȱȱȱǻƽŖDzȱǀDzȱȱŗǼȱ¡ȱȱǽǾǽŖǾȱƽȱŖȱȱȏȱ
ȱȱȱȱǻƽŖDzȱǀDzȱȱŗǼȱȱ¡ȱȱȱǽŖǾǽǾȱƽȱŖȱȱȏȱ
ȱȱȱȱȱȱȱǻƽŗDzȱǀDzȱȱŗǼȱ¡ȱ
ȱȱȱȱȱȱȱȱǻƽŗDzȱǀDzȱȱŗǼȱ¡ȱ
ȱȱȱȱȱȱȱȱȱȱȱ ȱǻ¡ƽ¢Ǽȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱƽȱŗȱƸȱǽȬŗǾǽȬŗǾȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱƽȱ¡ǻǽȬŗǾǽǾǰȱǽǾǽȬŗǾǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȏ ȱ
ȱȱȱȱȱȱȱȏȱ
ȱȱȱȏȱ
ȱȱȱȱǽǾǽǾȱ
ȏȱ ȏȱǻȱƽȱǿ¡ŗǰȱ¡Řǰȱdzǰȱ¡Ȁǰȱȱƽȱǿ¢ŗǰȱ¢Řǰȱdzǰȱ¢ȀǼȱ
ûȱȱȱȱȱȱȱȱ§ȱȱȱ¡ȱǽǾǽǾǯȱȱȬ
ȱ ȱ ¢ȱ Ѧ ѥ XQG ѫȱ ȱ ££ǰȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǽǾǽǾȱ ȱ ȱ ǻǰȱ ǰȱ £ ǯȱ Ǽǯȱ ȱ ȱ
ȱ§ȱȱȱǻȱȱȱ§ǰȱ ȱȱ ȱ Ǽȱ
ȱȱȱȱǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
Ŗȱ
¢
ŗȱ
Śȱ
Řȱ
şŖȱ
řȱ
ŝȱ
Śȱ
ŗŖȱ
śȱ
ŝŖȱ
Ŝȱ
Řȱ
ŝȱ
ŝŗȱ
Şȱ
Şŗȱ
şȱ
Ŗȱ
¡ȱ Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
Ŗȱ
ŗȱ ŗŖȱ Ŗȱ
ѦŖȱ
ѦŖȱ
ѦŖȱ
ѫŗȱ ѥŗȱ ѥŗȱ ѥŗȱ ѥŗȱ ѥŗ
Řȱ
Ŗȱ
Śȱ
Ŗȱ ѥŗȱ ѥŗȱ ѥŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ
řȱ ŘŖȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ
Śȱ ŗŖȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ ѫŘȱ ѥŘȱ ѥŘȱ ѥŘȱ ѥŘȱ ѥŘ
śȱ ŚŖȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ ѦŘȱ ѦŘȱ ѦŘȱ ѦŘȱ ѦŘȱ ѦŘȱ
Ŝȱ Řȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ ѦŘȱ ѦŘȱ ѫřȱ ѥřȱ ѥřȱ ѥř
ŝȱ Ŗȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ ѦŘȱ ѦŘȱ Ѧřȱ Ѧřȱ Ѧřȱ ѫŚȱ
Şȱ ŜŖȱ Ŗȱ Ѧŗȱ Ѧŗȱ Ѧŗȱ ѦŘȱ ѦŘȱ Ѧřȱ Ѧřȱ Ѧřȱ ѦŚȱ
ȱ
ȱȬDZȱȱȱȱ
8 Dynamische Programmierung
247
ȱȱȱȱȱȱȱȱ¢ȱ¡ǽǾȱȱ¢ǽǾȱȱ ǰȱȬ
ȱ ȱȱ¡ȱǽǾǽǾȱȱƸŗȱȱȱƸŗȱǰȱ ȱȱȱȬ
ȱȱŖȱ£ȱ DZ
int[][] c = new int[m + 1][n + 1];
ȱ ȱ ȱȱȬȱǰȱȱȱȱȱȱ¡ȱ
ȱ £ȱ ǯȱ ȱ ȱ §ȱ ȱ ȱ £ǰȱ ȱ ȱ
ǽǾǽǾȱ ȱ ȱ ȱ £ȱ ȱ ãȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱǯȱȱȱȱȱ£ȱ ȱȱȱȬȱȱȬ
ǯȱȱȱȱȱȱȱȱȱȱȱȱȱDZȱ
ȱ¡ǽǾȱƽȱ¢ǽǾȱȱǻȱȱȱȱȱûȱȱȱȱȱȱȱȱȱ
ûȱȱȱȱǼǰȱ ȱȱȱȱȱȱȱȱǽǾǽǾȱȬ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ £ûǯȱ
đȱȱ ȱȱȱȱ ȱȱȱǰȱ£ȱȱ ȱ
ȱȱȱȱŗǯȱ
ȱ¡ǽǾȱƾȱ¢ǽǾȱǰȱ ȱȱȱȱȱȱȱǽǾǽǾȱ ȱȱ
ȱȱȱȱȱȱ ǯȱȱȱȱȱȱ
£ȱȱȱȱ ǯȱȱȱtȱȱ ȱȱȱ
ǰȱ ȱ ȱ ȱ ȱ ŗȱ ǯȱ ȱ ȱ ȱ ȱ ûǰȱ ȱ ȱ
ȱȱ ǰȱ£ȱȱ ȱȱȱŗǯȱ
ȱ £ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ǰȱ ȱ ȱ ȱ ȱ £ȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ǻȱ ȱ
ȱ Ǽȱ ǯȱȱ ȱȱȱãǰȱȱȱȱȱ
ȱ £ȱ ǰȱ ȱ ȱ ¡ȱ ȱ §ȱ ȱ ȱ ȱ £Ȭ
£ǰȱȱȱȱ£ȱ§ȱȱȱȱȱ££ûǯȱ
Programm
ȱ
import java.io.*;
import java.util.*;
public class P03LCS {
private static final String FileInputName = "lcs.in";
private static final String FileOutputName = "lcs.out";
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
248
Grundlegende Algorithmen mit Java
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
int m = scanner.nextInt();
int n = scanner.nextInt();
int x[] = new int[m];
for (int i = 0; i < m; i++) {
x[i] = scanner.nextInt();
}
int y[] = new int[n];
for (int i = 0; i < n; i++) {
y[i] = scanner.nextInt();
}
int[][] c = new int[m + 1][n + 1];
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= n; ++j) {
if (x[i - 1] == y[j - 1]) {
c[i][j] = c[i - 1][j - 1] + 1;
continue;
}
;
if (c[i - 1][j] >= c[i][j - 1]) {
c[i][j] = c[i - 1][j];
} else {
c[i][j] = c[i][j - 1];
}
}
int ll = m, cc = n;
List<Integer> v = new ArrayList<Integer>();
while (ll != 0 || cc != 0) {
if (ll != 0 && cc != 0 && x[ll - 1] == y[cc - 1]) {
v.add(x[ll - 1]);
--ll;
--cc;
continue;
}
if (ll != 0 && c[ll][cc] == c[ll - 1][cc]) {
ll--;
continue;
}
if (cc != 0 && c[ll][cc] == c[ll][cc - 1]) {
cc--;
}
}
out.printf("Maximale Laenge: %d%n", c[m][n]);
8 Dynamische Programmierung
249
ListIterator<Integer> lit = v.listIterator(v.size());
while (lit.hasPrevious()) {
out.print(lit.previous());
out.print(' ');
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱȱȱȱǰȱȱȱ§ȱȱȬ
ȱȱǽǾǽǾȱǯȱ
ȱȱȱȱ Ȭ Ȭȱȱȱȱ ȱȬ
ǯǯ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭ
ǰȱȱȱȱȱ£ǯȱ
ȱȱȱȱȱûȱȱȬǯȱ
ǯȱ ȱȱȱǰȱȱȱ ȱȱȬ
ȱǻȱ≥ȱŘǼȱȱ§ȱȱȱǯȱ
Problem 4. Zahlen-Dreieck
ȱȱȱȱȱȱ ȱȱȱȱȱǰȱȱȱȱȬ
ȱȱ£ȱ£ȱȱǰȱȱ£ ȱǰȱȱǰȱȱȱȱȱǰȱ
ȱ£ȱȱȱȱȱȱȱȱ ǯȱȱȱȬ
ȱǰȱûȱȱȱȱȱȱȱ¡ȱǯȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ £ȱ ȱ Ȭǰȱ ȱ
ȱûȱȱ ȱȱǯȱȱȱȱȱȱȱȱȱȱ
ǯȱȱȱãȱŗŖŖȱǰȱȱȱȱȱȱȱȱŗŖŖǯȱ
DZȱ ȱȱȱǯȱȱ£ȱȱȱ¡ȱȱȱ Ȭ
ǰȱȱȱȱ§ȱȱȱȱȱǰȱȱȱȱȱ
ȱǯȱ
ȱ
dreieck.in
7
10
dreieck.out
Maximale Summe = 346
1
250
82 81
4 6 10
2 14 35 7
41 3 52 26 15
32 90 11 87 56 23
54 65 89 32 71 9 31
Grundlegende Algorithmen mit Java
2
3
3
3
4
5
ǻ ǰȱ ǰȱŗşşŚǼȱ
Problemanalyse und Entwurf der Lösung
ȱ §ȱ ȱ ãđȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱ£ȱȱãȱûǯȱȱ ȱȱȱȱȱȱ
ŞŘȱ ȱ ȱ £ ȱ ȱ §ȱ ûǰȱ ȱ §ȱ ȱ ãȱ ǰȱ ȱ
ȱ£ȱ §ǰȱȱȱřŚŜȱǻȱãǼǯȱ
ȱ
ȱ £ȱ ȱ ȱ ȱ ¢ȱ ǽǾǽǾȱ ǰȱ ȱ ȱ ¢ȱ ǽǾǽǾȱ ȱ Ȭ
ȱDZȱ
ȱ
ǽǾǽǾȱȱȱãđȱǰȱȱȱȱȱȱȱȱȱ£ȱȱǰȱȱ
ǽǾǽǾȱǰȱȱ ȱǯȱ
ȱ
ȱȱȱȱûȱȱǽǾǽǾȱ£ȱǰȱ ȱ ȱȱ¢ȱǽŗŖŖǾǽŗŖŖǾǰȱ
ȱȱDZȱ
ǽǾǽǾȱƽȱȮŗȱûȱȱȱǰȱȱ
ǽǾǽǾȱƽȱŖǰȱ ȱȱȱǰȱȱȱǽǾǽǾȱǰȱȱȱȱǽȬŗǾǽȬŗǾȱ
ȱǯȱȱȱȱȱȱȱǯȱȱ
ǽǾǽǾȱ ƽȱ ŗǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ǽǾǽǾȱ ǰȱ ȱ ȱ ȱ ǽȬŗǾǽǾȱ
ȱǯȱȱȱȱȱȱȱǯȱ
ǽǾǽŖǾȱȱȱŗǰȱ ȱȱȱȱȱȱȱȱûȱȱ
ȱȱǻȱȱȱȱǽȬŗǾǽȬŗǾǷǼǯȱ
ȱ ȱ ȱ §ȱ ȱ ¢ȱ ǽǾȱ ǰȱ ǽǾȱȱ ȱȱ ȱ ȱ ȱ ȱ
ȱȱȱȱǯȱȱȱ¢ȱǽǾǽǾȱȱ ǽǾȱȱ ǰȱȬ
ȱ ȱ ȱȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ǽǾǽǾǯȱ ȱ ȱ ȱ ȱ
ȱDZȱ
ȱ
w[n - 1] = 0;
for (int j = 0; j <= n - 1; j++)
if (s[n - 1][j] > s[n - 1][w[n - 1]]) {
w[n - 1] = j;
}
ȱ
ȱãȱ ȱȱ ȱȱǽǾǽǾȱȱãȱȱ ȱDZȱ
ȱ
ȱ
8 Dynamische Programmierung
251
for (int i = n - 2; i >= 0; i--) {
if (vPred[i + 1][w[i + 1]] == 0)
w[i] = w[i + 1] - 1;
ȦȦȱȱȱȱ
else
w[i] = w[i + 1];
ȦȦȱȱȱȱ
}
ȱ
Programm
import java.io.*;
import java.util.*;
public class P04Triangle {
private static final String FileInputName = "dreieck.in";
private static final String FileOutputName = "dreieck.out";
static void process(int a[][], int n, int s[][],
int vPred[][], int w[]) {
s[0][0] = a[0][0];
vPred[0][0] = -1;
for (int i = 1; i < n; i++) {
s[i][0] = a[i][0] + s[i - 1][0];
vPred[i][0] = 1;
for (int j = 1; j <= i; j++) {
if (s[i - 1][j - 1] >= s[i - 1][j]) {
vPred[i][j] = 0;
s[i][j] = a[i][j] + s[i - 1][j - 1];
} else {
vPred[i][j] = 1;
s[i][j] = a[i][j] + s[i - 1][j];
}
}
}
w[n - 1] = 0;
for (int j = 0; j <= n - 1; j++)
if (s[n - 1][j] > s[n - 1][w[n - 1]]) {
w[n - 1] = j;
}
for (int i = n - 2; i >= 0; i--) {
if (vPred[i + 1][w[i + 1]] == 0)
w[i] = w[i + 1] - 1;
else
w[i] = w[i + 1];
}
}
252
Grundlegende Algorithmen mit Java
static void writeData(PrintStream out, int s[][],
int w[], int n) {
out.print(" Maximale Summe = ");
out.println(s[n - 1][w[n - 1]]);
for (int i = 0; i < n; i++) {
out.println(w[i] + 1);
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
int n = scanner.nextInt();
int a[][] = new int[n][];
int s[][] = new int[n][];
int vPred[][] = new int[n][];
int w[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = new int[i + 1];
s[i] = new int[n];
vPred[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
a[i][j] = scanner.nextInt();
}
}
process(a, n, s, vPred, w);
out = new PrintStream(new File(FileOutputName));
writeData(out, s, w, n);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱȱûȱȱȱ ǵȱȱȱȱ Ȭ
ȱûȱȱȱǻǰȱǼǵȱȱ
ȱȱǰȱȱȱȱȱȱȱ¡ȱȱǯȱȬ
ȱȱȱȱǰȱȱȱȱȱȱ ǯȱ
8 Dynamische Programmierung
řǯ
Śǯ
śǯ
253
ûȱȱȱȱȱȱ£ǰȱȱȱȱȱûȬ
ȱȱȱȱǻǰȱǼȱǯȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ £ȱ ȱ
ȱ£ȱǯȱ
ȱȱȱǰȱȱȱȱȱȱȱȱǰȱȱ£ȱ
§ȱȱ£ȱǯȱûȱȱȱȱǷȱ
Problem 5. Domino
ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱȱȱȱǯȱȱȱȱ§Ȭ
ȱ ȱ ȱ ǰȱ ȱ ȱ ûȱ £ ȱ Ȭ
ȱ ȱ ȱ DZȱ ȱ £ ȱ ȱ ȱ
ȱȱȱȱȱȱȱȱ£ ȱ
ȱûǯȱȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱǯȱ ȱȱȱȱȱȱŗȱȱŜǯȱ
DZȱ ȱ ȱ ȱ ǯȱ ȱ ȱ £ȱ ȱ ¡ȱ ȱ ȱ ȱ
ǯȱ ȱȱ§ȱȱ ȱȱȱȱȱǯȱȬ
DZȱ
ȱ
domino.in
5 6
1 1
2 5
3 2
1 5
6 4
5 1
5 3
2 1
1 4
5 5
5 2
3 3
domino.out
6
6 5
5 2
2 3
3 5
5 5
5 2
ǻȱǽŖŖǾǼȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ǰȱ ȱ ȱ
ȱ£ȱȱȱ £ȱȱ¡ȱ ȱŖśȱǯȱ£ȱȬ
£ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻǼDZȱ ȱ ǻǰȱ Ȭ
ǯ¡ ǻǼǼǯȱȱȱȱȱȱǰȱȱȱȱȱȱȬ
ȱ¢ǰȱȱȱ ȱȱȱû£ȱDZȱ
254
Grundlegende Algorithmen mit Java
Ȭ
Ȭ
Ȭ
Ȭ
ȱ ȱ ǻȱ ǰȱ ȱ Ǽȱ £ȱȱ ȱ ȱ ȱ Ȭ
ȱȱȱȱDzȱ
ǻȱǰȱȱǼȱûǰȱȱȱȱȱȱȱȱ£Ȭ
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ Ȭ
ȱȱȱDzȱ
ǻǼȱȱȱȱȱ¢ȱȱ£ûǰȱȱȱȱȱ
ȱǯDzȱ
ȱ ûȱ ȱ ǻǼȱ ȱ ǯǯȱ ȱ ȱ ȱ ¢ȱ
ȱȱȱûȱȱǯȱ
ȱ
ȱȱ£ ȱ¢DZȱ
ȱ
ǽŘŖŖǾǽŘǾȱȱȱDZȱ
ǽǾǽŖǾȱƽȱȱ¡ȱ§ȱȱȱȱǰȱȱȱȱȱȱȱ
§ǰȱȱȱȱȱ
ǽǾǽŗǾȱƽȱȱ¡ȱ§ȱȱȱȱǰȱȱȱȱȱȱȱ
§ǰȱȱȱȱ
ȱ
¡ǽŘŖŖǾǽŘǾǰȱȱȱDZȱ
¡ǽǾǽŖǾȱȱƽȱȱȱȱȱȱǻȱȱȱǼȱȱȱ¡ȱȱ
ȱȱȱȱȱȱȱȱȱǰȱȱȱȱȱȱǯȱ
ȱ¡ǽǾǽŗǾȱƽȱȱȱȱȱȱǻȱȱǼȱȱȱ¡ȱȱ
ȱȱȱȱȱȱȱȱȱǰȱȱȱȱȱȱǯȱ
ȱ
ȱȱ£ ȱȱDZȱ
¡ȱȱ ȱ
ƽȱ¡ȱûȱȱ ȱ¡ȱȱ
ȱǻŖȱȱŗǼȱȱȱ ƽȱȱȱȱȱȱȱ¡ȱǰȱȱȱ¡ȱȱȱȱȱȱȱȱȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ§ȱ ȱǻŖǰȱ ȱȱǰȱȱŗǰȱ ȱǼǯȱ
ȱ
ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ȱ ǽǾǽŖǾȱ ȱ ǽǾǽŗǾȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱȱȱȱȱ¡ȱȱǯȱ
ȱ
ȱȱ ǻǼȱû§ȱȱȱȱȱǯȱȱ ȱȱ
ȱ¢ȱȱȱȱȱȱ¡ȱȱǯȱ ȱ¡ȱ ȱ ȱȱ
£ ȱȱȱ ȱȱȱȱ¡ȱȱǰȱȱȱȬ
ȱȱȱȱ£ȱȱǻ ȱ ȱȱȱ¡ǽǾǽǾǰȱ ȱȱ
ȱ Ǽǯȱ
ȱ
8 Dynamische Programmierung
255
Programm
import java.io.*;
import java.util.*;
public class P05Domino {
private static final String FileInputName = "domino.in";
private static final String FileOutputName = "domino.out";
private static class Piece {
int first, second;
Piece(int first, int second) {
this.first = first;
this.second = second;
}
boolean fits(Piece other, boolean reversed){
return second == (reversed ? other.second : other.first);
}
Piece reverse(){
return new Piece( second, first );
}
public String toString() {
return first + " " + second;
}
}
private List<Piece> vP;
int iMax, bit;
int vNext[][], v[][];
P05Domino(List<Piece> pieces) {
this.vP = pieces;
this.vNext = new int[pieces.size()][2];
this.v = new int[pieces.size()][2];
}
void doProcess() {
int n = vP.size();
v[n - 1][0] = 1;
vNext[n - 1][0] = n;
v[n - 1][1] = 1;
vNext[n - 1][1] = n;
iMax = n - 1;
bit = 0;
256
Grundlegende Algorithmen mit Java
for (int i = n - 2; i >= 0; i--) {
v[i][0] = 1;
vNext[i][0] = n;
v[i][1] = 1;
vNext[i][1] = n;
for (int j = i + 1; j < n; j++) {
if ( vP.get(i).fits(vP.get(j), false) &&
v[i][0] < v[j][0] + 1 ) {
v[i][0] = v[j][0] + 1;
vNext[i][0] = j;
}
if (vP.get(i).fits(vP.get(j), true) &&
v[i][0] < v[j][1] + 1) {
v[i][0] = v[j][1] + 1;
vNext[i][0] = j;
}
if (vP.get(i).reverse().fits(vP.get(j), false) &&
v[i][1] < v[j][0] + 1) {
v[i][1] = v[j][0] + 1;
vNext[i][1] = j;
}
if (vP.get(i).reverse().fits(vP.get(j), true) &&
v[i][1] < v[j][1] + 1) {
v[i][1] = v[j][1] + 1;
vNext[i][1] = j;
}
}
int auxMax = v[i][0] > v[i][1] ? v[i][0] : v[i][1];
if (auxMax > v[iMax][bit]) {
iMax = i;
bit = v[i][0] >= v[i][1] ? 0 : 1;
}
}
}
void write(PrintStream out) {
int aux;
out.println(v[iMax][bit]);
int n = (int) vP.size();
if (0 == bit) {
aux = vP.get(iMax).second;
out.println(vP.get(iMax));
} else {
aux = vP.get(iMax).first;
out.println(vP.get(iMax).reverse());
}
iMax = vNext[iMax][bit];
while (iMax != n) {
8 Dynamische Programmierung
257
if (aux == vP.get(iMax).first) {
out.println( vP.get(iMax) );
aux = vP.get(iMax).second;
bit = 0;
} else {
out.println(vP.get(iMax).reverse());
aux = vP.get(iMax).first;
bit = 1;
}
iMax = vNext[iMax][bit];
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
List<Piece> vP = new ArrayList<Piece>();
while (scanner.hasNextInt()) {
int first = scanner.nextInt();
vP.add(new Piece(first, scanner.nextInt()));
}
P05Domino domino = new P05Domino(vP);
domino.doProcess();
out = new PrintStream(new File(FileOutputName));
domino.write(out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ȱ
ŗǯ
ȱȱȱ§ȱȱǯȱ
Řǯ
řǯ
û£ȱȱȱȱȬǯȱ
ȱȱȱȱ£ ȱ¢ȱǽǾǽǾȱ£ ȱȬ
ȱ¢DZȱǽǾȱȱ ǽǾǽŖǾȱȱǽǾȱȱ ǽǾǽŗǾǯȱ ȱȱȱȬ
ȱȱǯȱ
258
Grundlegende Algorithmen mit Java
Problem 6. Verteilung der Geschenke
ȱ ûȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ ȱ ȱ ǯȱ
ȱ ȱ ûȱ ǰȱ ȱ ȱ ǰȱ ûȱ
ȱ ȱ ȱ ȱ ǯȱ ȱ
ȱǰȱȱȱ ȱȱȱ£ ȱŗȱ
ȱŗŖŖȱȱȱȱȱ¡ȱśŖȱ ȱûȱ
ȱ ûȱ ǯȱ £ȱ ȱ ȱ ǰȱ ȱ
ȱ ȱȱȱȱãȱȱ
ǯȱ
ȱDZȱ ȱ ǯȱ ȱ ȱ Ȭ
ȱ ûȱ ȱ DZȱ ȱ £ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱ£ ǯȱ
DZȱ ȱȱȱǯȱȱȱȱȱȱȱ ǰȱ ȱȱ
ȱ ȱȱ ȱ ȱǰȱȱ£ ȱǯȱȱ£ ȱȱȱȱ
ȱȱȱûȱȱ ȱûȱȱȱûǯȱDZȱ
ȱ
geschenke.in
7
28 7 11 8 9 7 27
15
12 43 8 90 13 5 78 34 1 97 31 65 80 15 17
geschenke.out
48 49
28 11 9
7 8 7 27
294 295
12 43 90 13 5 34 97
8 78 1 31 65 80 15 17
ǻ ǰȱǰȱŗşşśǼȱ
Problemanalyse und Entwurf der Lösung
ȱȱ ȱ §ǰȱȱȱȱ ȱ£ȱȱȱȱȱȱ
ȱ£ȱǯȱȱȱȱ£ǰȱȱȱ ¡§ȱȱ¡ǯȱȱ
ȱûȱȱ¢ȱǽǾȱȱȱȱȱ ǯȱȱȱãȬ
ãȱȱȱȱȱȱǽǾȱȱȱDZȱ
ȱ
- ǽŖǾȱƽȱŖȱ
- ǽǾȱƽȱǰȱûȱȱ∈ǿŗǰȱǯǯǰȱȀǰȱǯǯȱȱ£ȱûȱǰȱȱȱ ȱ
ȱ£ȱǰȱȱǽǾDzȱ
- ǽǾȱƽȱInteger.MAX_VALUEǰȱ ȱȱȱȱȱȱ ȱǯȱ
ȱȱȱȱȱȱȱȱ ǯȱȱȱ ȱ
ȱ ȱ ȱ ǽǾȱ ȱ ȱ ȱ ȱ ȱ ûȱ ǰȱ ȱ ȱ ȱ ȱ
ȱƸǽǾǯȱȱȱDZȱǽǾȱǀȱȱǻȱ ȱȱȱȱ£ȱȱ
8 Dynamische Programmierung
ȱ £ûȱ
ȱȱ£ȱ
ǰȱ ȱ ȱ
259
ȱ ȱ Ǽǯȱ
aS[0] = 0;
Arrays.fill(aS, 1, aS.length, Integer.MAX_VALUE);
for (int i = 1; i <= presents.length; i++)
for (int j = 0; j <= sumDiv2 - aPresents[i - 1]; j++)
if (aS[j] < i &&
Integer.MAX_VALUE == aS[j + aPresents[i - 1]]) {
aS[j + aPresents[i - 1]] = i;
}
ȱ
ȱȱȱǽǾȱǯȱȱǰȱ ȱȱȱǻǼȱȱ ȱȬ
ǯǯ¢ȱȱȱȱȱ ȱȱ¢ȱȱȱȱȬ
ǯȱDZȱ
ȱ
fill(Object[] a, int fromIndex, int toIndex, Object val)ȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ Ȭ
ȱãȱȱǯȱ £ȱãȱ ȱȱȱȱȱȱȬ
ȱ ǯȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ
ǻǼǯȱȱȱȱ¢ȱǽǾȱȱ ȱȱŗǰȱȱȱȱûȱ
ãȱǻȱ ȱȱȱȱȱȱǽǾȱȱŖǼDZȱ
ȱ
if (aS[i] > 0) {
int idx = aS[i] - 1;
recoverPresents(i - aPresents[idx], out);
out.print(aPresents[idx]);
out.print(' ');
bset.set(idx);
}
ȱ
Programm
import java.io.*;
import java.util.*;
public class P06Presents {
private static final String FileInputName = "geschenke.in";
private static final String FileOutputName = "geschenke.out";
private int aPresents[];
private int sum;
private BitSet bset;
private int aS[];
260
Grundlegende Algorithmen mit Java
P06Presents(int[] presents) {
this.bset = new BitSet();
this.aPresents = presents;
for (int i : presents) {
this.sum += i;
}
int sumDiv2 = sum / 2;
this.aS = new int[sumDiv2 + 1];
aS[0] = 0;
Arrays.fill(aS, 1, aS.length, Integer.MAX_VALUE);
for (int i = 1; i <= presents.length; i++)
for (int j = 0; j <= sumDiv2 - aPresents[i - 1]; j++)
if (aS[j] < i &&
Integer.MAX_VALUE == aS[j + aPresents[i - 1]]) {
aS[j + aPresents[i - 1]] = i;
}
}
private void recoverPresents(int i, PrintStream out) {
if (aS[i] > 0) {
int idx = aS[i] - 1;
recoverPresents(i - aPresents[idx], out);
out.print(aPresents[idx]);
out.print(' ');
bset.set(idx);
}
}
void write(PrintStream out) {
for (int i = sum / 2; i >= 0; i--)
if (aS[i] != Integer.MAX_VALUE) {
out.print(i);
out.print(' ');
out.println(sum - i);
recoverPresents(i, out);
out.println();
break;
}
for (int i = 0; i < aPresents.length; i++)
if (!bset.get(i)) {
out.print(aPresents[i]);
out.print(" ");
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
8 Dynamische Programmierung
261
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
int aPresents[] = new int[scanner.nextInt()];
for (int i = 0; i < aPresents.length; i++) {
aPresents[i] = scanner.nextInt();
}
P05Presents p = new P05Presents(aPresents);
out = new PrintStream(new File(FileOutputName));
p.write(out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
ȱȱȱȱȱ Ȭ ȬȱȱȱȱȱȬ
ȱȱ ȱǯǯ¢ȱǯȱȱȱȱǰȱȱ
ȱ ȱ ȱ ǻǼǰȱ ǻǼȱ ȱ ¢ǻǼȱ ȱ ȱ ȱ
ǯȱ
Problem 7. Ähnliche Summe
ȱȱȱûȱȱȱȱȱȱȱûȱȱǯȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ£ȱȱȱȱȱ£ȱȱȱȱȱûǯȱǯȱǯȱãȱ
ûȱ ȱ ƽȱ ŚśŜşȱ ȱ ȱ ƽȱ ǿŚśřŚśǰȱ ŜśŞşŘǰȱ ŝŞŜŝŞǰȱ ŗŗŗŗśřǰȱ ŗşŖŘŘřǰȱ ŜŝśŚśŗǰȱ śŚřŞŝŜǰȱ ŘřşŞŖǰȱ
şşŚśřǰȱşşŖŗŘŗǰȱŜśŜśśśǰȱŚřŘşŖŞǰȱŗŘřŜŗȀȱȱȱƽǿŘřşŞŖǰȱŜŝśŚśŗǰȱŗşŖŘŘřǰȱŝŞŜŝŞǰȱ
ŜśŞşŘǰȱŚśřŚśȀȱȱDZȱȱ
ȱ
ŘřşŞŖȱƸȱŜŝśŚśŗȱƸȱŗşŖŘŘřȱƸȱŝŞŜŝŞȱƸȱŜśŞşŘȱƸȱŚśřŚśȱƽȱŗŖŝşśŜşȱ
ȱȱ
ûȱ ȱ ƽȱ Şȱ ȱ ȱ ƽȱ ǿŜśşŜŞǰȱ ŜśŚřŘǰȱ ŜśŚřşŞŝŜǰȱ şŖŝŞŜśśǰȱ śŜŝŚřǰȱ śŚřŘŗǰȱ ŜśŚřŘşŞǰȱ ŚśřŗŘşǰȱ
śŚřŘŗǰȱşşşşşşşǰȱśŜŝśŚřȀȱãȱȱȱȱȱǿşşşşşşşǰȱŜśŚřŘşŞǰȱśŜŝŚřǰȱŜśşŜŞȀȱ
DZȱȱ
şşşşşşşȱƸȱŜśŚřŘşŞȱƸȱśŜŝŚřȱƸȱŜśşŜŞȱƽȱŗŜŜŜŜŖŖŞȱ
ȱ
262
Grundlegende Algorithmen mit Java
DZȱ ȱȱȱ£ǯȱȱȱȱûȱȱǰȱȱȱȱȬ
ȱ ȱ ȱ ȱ ǻȱ ȱ ǽŖǰȱ ŘǯŖŖŖǯŖŖŖǯŖŖŖǾǼǯȱ DZȱ ȱ ȱ ȱ £ǯȱ ȱ
ȱȱȱȱȱȱǰȱ ȱȱȱȱûǰȱ
ǯȱȱȱ ȱȱȱȱǰȱȱûȱȱȱȱȱ
ȱǯȱȱȱȱãȱǰȱȱȱDZȱȱǷǯȱDZȱ
ȱ
zahlen.in
4569
45345 65892 78678 111153 190223
675451 543876 23980 99453 990121
656555 432908 12361
8
65968 65432 65439876 9078655 56743
6543298 453129 54321 9999999 567543
45678
65432 65439876 9078655 56743 54321
6543298 453129 54321 9999999 567543
zahlen.out
23980 675451 190223 78678 65892
45345
9999999 6543298 56743 65968
keine Loesung!
Problemanalyse und Entwurf der Lösung
ȱȱȱȱśȱȱ§ǯȱȱ
ȱȱȱ¢ȱǽǾȱȱŗŖŖŖȱȱǰȱȱ ȱȱȬŗȱǯȱ Ȭ
ȱ ȱ ȱȱȱȱȱȱȱȱȱǰȱûȱ ȱ
ǯȱȱ ȱȱȱȱȱ ȱDZȱȱ
- ǽ¡¢£Ǿȱ§ȱȬŗǰȱ ȱȱȱȱȱ ǰȱȱ£ȱ
ȱȱ¡¢£ȱDzȱ
- ǽ¡¢£Ǿȱ §ȱ ȱ ¡ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ £ȱ
ȱȱȱȱǰȱȱ£ȱȱȱ¡¢£ȱǯȱ
ȱ
ȱ£ǯȱǯȱȱȱȱȱȱȱȱȱȱŚśřŚśȱǰȱ ȱǽřŚśǾȱ
ȱŖȱ£ǰȱ ȱ ȱȱ ¡ȱȱ£ǯȱȱŖȱ£§ǯȱȱȱȱȱȱȱ
ȱȱȱȱȱǯȱȱȱȱ ȱȱȱǻ¡ȱ
←ȱǽǾǰȱûȱƽŖǰȱŗǰȱŘǰȱdzǼDZȱ
ȱ
•
ȱȱȱȱȱȱ ǰȱȱȱȱ£ȱȱȬ
ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ¡ȱ ûȱ ǻǽ¡ƖŗŖŖŖǾƽƽȬ
ŗǼǰȱȱȱ ȱȱ ¡ȱȱȱȱȱȱǽ¡ƖŗŖŖŖǾDZȱ
int aux = vElem.get(i);
if (-1 == vLast[aux % 1000]) {
vLast[aux % 1000] = i;
}
ȱ
8 Dynamische Programmierung
•
263
ûȱ ȱ ȱ ȱ ȱ ȱ ǻǽǾƾȬŗǼȱ ȱ ȱ ȱ ãȬ
ȱ£ȱȱȱȱǰȱȱ ȱȱãǰȱ ȱ ȱ¡ȱ
ȱ ǻ←ǻ¡ƸǼƖŗŖŖŖǼǯȱ ȱ ȱ £ȱ ȱ ãȱ ȱ
ȱãȱȱȱǽǾȱȱȬŗȱǰȱȱ ȱȱȱDZȱȱ
ȱ
for (int j = 0; j < 1000; j++) {
if (vLast[j]!=-1 && j!=aux%1000 && vLast[j]!=i) {
int sum = (aux + j) % 1000;
if (-1 == vLast[sum]) {
vLast[sum] = i;
}
}
}
ȱ
ȱ ȱ ȱ ȱ ȱ ǽǾȱ ȱ ȱ ȱ ȱ Ȭŗȱ ȱ ȱ
ǰȱ§ȱ ȱȱȱǯȱȱ ȱȱȱǽǾȱãȱ ȱȱȬ
ȱȱ ȱȱȱDZȱ
ȱ
ȱȱƽȱdzǯŗŘŝȱȱ£ȱȱ
ȱȱƽȱdzśŚřȱȱǻŗŘŝǁśŚřǼǰȱȱȱ
ȱ←ȱdzśŞŚȱǻŗŗŘŝȬśŚřǼȱ
ȱȱƽȱdzǯśŚřȱȱ£ȱȱ
ȱȱƽȱdzŗŘŝȱȱǻŗŘŝǀśŚřǼǰȱȱ
ȱ←ȱdzŚŗŜȱǻśŚřȬŗŘŝǼȱ
while (vLast[i] >= 0) {
out.print(' ');
out.print(vElem.get(vLast[i]));
int j = i;
if (i < vElem.get(vLast[i]) % 1000) {
i = 1000 + i - vElem.get(vLast[i]) % 1000;
} else {
i = i - vElem.get(vLast[i]) % 1000;
}
vLast[j] = -1;
}
ȱȱ
Programm
import java.io.*;
import java.util.*;
public class P07SameSums {
private static final String FileInputName = "zahlen.in";
private static final String FileOutputName = "zahlen.out";
private static final int MinusEins = -1;
264
Grundlegende Algorithmen mit Java
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
int start = scanner.nextInt();
List<Integer> vElem = new ArrayList<Integer>();
while (scanner.hasNextInt()) {
vElem.add(scanner.nextInt());
}
int vLast[] = new int[1000];
Arrays.fill(vLast, MinusEins);
for (int i = 0; i < vElem.size(); i++) {
int aux = vElem.get(i);
if (MinusEins == vLast[aux % 1000]) {
vLast[aux % 1000] = i;
}
for (int j = 0; j < 1000; j++) {
if (vLast[j] != MinusEins &&
j != aux % 1000 && vLast[j] != i) {
int sum = (aux + j) % 1000;
if (MinusEins == vLast[sum]) {
vLast[sum] = i;
}
}
}
}
int i = start % 1000;
if (i != 0)
vLast[0] = MinusEins;
if (vLast[i] != MinusEins) {
while (vLast[i] >= 0) {
out.print(' ');
out.print(vElem.get(vLast[i]));
int j = i;
if (i < vElem.get(vLast[i]) % 1000) {
i = 1000 + i - vElem.get(vLast[i]) % 1000;
} else {
i = i - vElem.get(vLast[i]) % 1000;
}
vLast[j] = MinusEins;
}
} else
8 Dynamische Programmierung
265
out.print("keine Loesung!");
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgaben
ŗǯ
ȱ ȱ ãȱ ȱ ǰȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
£ȱ ȱ ȱ ûǵȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
ȱȱ£ȱȱ£ȱȱûȱǰȱȱȱȱ
ȱȱȱ DZȱȱȱ
ȱ
zahlen1.in
4569
45345 65892 78678 111153
190223 675451 543876 23980
99453 990121 656555 432908
12361 65432 453219
781
65968 65432 65439876
9078655 56743 6543298
453129 54321 9999999 567543
4565 67543 45365 34546
zahlen1.out
...569: 7
23980 675451 190223 78678 65892
45345
...781: 5
567543 54321 6543298 56743
65439876
ȱ
ȱ ¡ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ûȱ
ȱǰȱȱȱȱȱûȱȱ§ǰȱ¡ȱȬ
ȱȱȱ ¡ǯȱȱȱȱǰȱȱ ¡ȱ¡Ȭ
ȱȱ£ȱǯȱ
ȱ
Řǯ
ȱ
řǯ
ȱȱȱȱǰȱȱȱȱ§ȱȱȱǻȱȱ
ȱ¡ȱ£ȱȱǼǯȱ
ȱȱȱȱȱȱȱȱȱǯȱ§£ȱ
ȱȱȱȱȱȱǯȱ
ȱ
Śǯ
ȱ
£ȱȱȱȱǰȱȱȱȱȱǻȱ Ǽȱ
ȱȱȱûǯȱ
266
Grundlegende Algorithmen mit Java
śǯ
ȱȱǰȱȱȱȱȱȱȱȱȱǻȱȱWDzȱŖȱ≤ȱȱ≤ȱŗŖŖŖǰȱȬ
ȱ ȱ ãđȱ ȱ Ŗȱ ȱ ȱ ȱ ŘǯŖŖŖǯŖŖŖǯŖŖŖǼǯȱ ȱ ȱ ȱ
ȱȱȱȱȱȱǰȱȱȱȱȱȬȱ£ȱ
ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
ȱȱûǯȱ
Ŝǯ
ȱȱȱȱȱȱȱȱȱȱȱ¡ȱ
řȱȱǯȱȱȱȱȱȱȱȱȬ
ǰȱȱȱȱȱȱȱûȱȱǯȱȱ
ȱȱȱȱûǯȱDZȱ
ȱ
ȱ
numbers4.in
0.123 6.789 10.125
115.117 11.03 12.12 7511.1
315.79 113.02 17.985
ȱ
ŝǯ
numbers4.out
10.125 7511.1 315.79 17.985
ȱȱȱǰȱȱȱȱûȱȱȱǯȱȱȱ
ȱ ȱȱǯȱ
Problem 8. Schotten auf dem Oktoberfest
ȱȱȱȱ ȱȱȱȱǯȱȱȱȱûȬ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ ǯȱ
ȱȱȱ ȱ£ȱȱȱȱȱǰȱȱȱ
ûȱ£ ȱȱ ȱǯȱȱȱȱȱŘȱǰȱȱȱȱûȱȱ
ȱȱȱȱǯȱȱûȱȱȱȱ£ ȱȱđȱ ȱǯȱ
ȱȱ£ȱǰȱȱȱȱ£ȱǰȱȱû£ȱȱ£ȱ
ǰȱ ȱȱ ȱȱǯȱȱȱȱȱ ȱȱû£ȱȱȱ
ȱǮ ȃȱȱȱȱȱȱǮȃȱȱ£ ǯȱûȱȱȱȱãȬ
ǰȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ȱ ǯȱ £ȱ ȱ ȱ ȱ
ȱ ȱȱȱǰȱȱȱ ȱȱ£ȱȱȱǰȱȱ
ǯȱ
ȱ đȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ
ǵȱȱ
DZȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ Ǯ Ȭ
ȃȱȱŘȬŘȱûǯȱȱ£ȱȱȱ£ ȱȱȱûȱȱȱ
ȱȱûǵȱ
ȱ
ȱ
ȱ
ȱ
8 Dynamische Programmierung
267
DZȱ ȱǯȱȱȱûȱȱǰȱȱ£ ȱŗȱȱ
śŖŖȱȱȱȱ§ȱǻŘȱȱȱȱȱǼǯȱ
DZȱ ȱ ȱ ûȱ ȱ
ȱ ȱ ȱ ȱ Ȭ
ǯǰȱȱȱȱ ȱDZȱȱȱȱ
ǰȱ ȱ ȱ ȱ §ȱ ȱ
ȱȱȱȱȬ
ȱ ȱ ȱ Śȱ £Ȭ
ȱȱȱǯȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
DZȱ
ȱ
oktoberfest.in
1
2
3
4
5
6
56
345
432
500
oktoberfest.out
1: 0.0000
2: 0.5000
3: 0.6250
4: 0.6875
5: 0.7266
6: 0.7539
56: 0.9241
345: 0.9696
432: 0.9728
500: 0.9747
ǻȱȱȬȱȱȱŗşşŜǰȱȱǯȱǼȱ
268
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱ ǰȱ ȱ ȱ ȱ ȱ û£ȱ ȱ ȱ ǰȱ ȱ ƙǯȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ£ȱȱȱȱǯȱȱǰȱȱȱ£ȱȱȱ
ȱǰȱȱȱŗȬǯȱȱ£ȱ ȱȱǻǰȱǼȱȱȱ
ûǰȱȱȱȱûȱȱȱǮ ȃȱ ȱ ǯȱ ȱȱȱƽȱŖȱȱȱƽȱȱȱǻǰȱ
ǼȱƽȱŗȦŘDZȱ
P(m,0) = P (m, m) =
1
2m
ȱ
ȱ §ȱ ȱ DZȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǰȱȱƙǯȱȱ§ȱƙȱ⋅ȱƙǰȱ ȱȱȱ£ ȱȱȱ ȱȱȱƜȱ
⋅ȱ ƙȱ ƽȱ ŗȦŘřǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ
ȱȱȱǰȱȱȱȱȱȱȱŖȱȱŗȱ
ȱȱ§ȱǰȱȱ£ȱ §ǰȱȱȱȱȱDzȱȱȱȱǰȱȱ
ȱ£ȱȱȱȱŘǯǯǯǼǯȱȱȱ≠ȱŖȱȱȱ≠ȱǰȱȱȱȱȬ
DZȱ
ȱ
1
1
P (m, s ) = P (m − 1, s ) + P (m − 1, s − 1) ȱ
2
2
ȱ
ȱȱȱȱûȱȬȱǮ ȃȱ£ȱǰȱȱ
ȱǰȱ
ǻǰȱǼȱƽȱ
ȱȱ£ȱ ǰȱ ȱȱȱȬŗȱûȱȱȱȬȱ
Ǯ ȃȱȱ
ȱǰȱ
Ǯ ȃȱ£ȱ ǰȱ ȱȱȱȬŗȱûȱȱȱǻȬŗǼȬȱ
Ǯ ȃȱȱ
ƙǻȬŗǰȱǼȱ
ȱ
ȱȱ DZȱ
­1
°° m , wenn s ∈ {0 , m}
P (m, s ) = ® 2
° 1 ⋅ P (m − 1, s ) + 1 ⋅ P (m − 1, s − 1), wenn s ∈{1, 2 , ..., m-1}
2
¯° 2
ȱ
Ƹȱ
ƙǻȬŗǰȱȬŗǼȱ
8 Dynamische Programmierung
269
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãȱ £ȱ ȱ ȱ
DZȱ ǻŘȬŘǰȱ ȬŗǼȱ ǻȱ ȱ ȱ ȱ ŘȬŘȱ ûȱ §ȱ ȱ ǻȬŗǼȬȱ ȱ
ȱȱȱȱȱǰȱǯǯȱȱȱ ȱǼǯȱȱ ȱ£ȱ
ȱȱȱŗȬǻŘȬŘǰȱȬŗǼǯȱ
ȱ
Programm 1.ȱȱȱȱȱȱȱDZȱ
import java.io.*;
import java.util.*;
public class P08Oktoberfest1 {
private static double f(int n) {
double r = 1;
for (int i = 0; i < n; i++)
r *= 0.5;
return r;
}
private static double p(int m, int q) {
if (q == 0 || q == m)
return f(m);
return 0.5 * p(m - 1, q) + 0.5 * p(m - 1, q - 1);
}
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Wahrscheinlichkeit: ");
int n = scanner.nextInt();
System.out.printf(Locale.ENGLISH, "%.4f%n",
1 - p(2 * n - 2, n - 1));
} finally {
scanner.close();
}
}
}
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱDZȱȱ£Ƿȱȱ ȱǰȱ ȱȱȬ
£ȱûȱȱǁȱŗŘȱȱ §ǯȱȱǰȱ ȱȱȱǻ ȱȱȱȱȬ
ȬǼȱȱȱȱǯȱ ȱȱȱȱȱûȱǻśǰȱřǼDZȱ
ȱ
270
Grundlegende Algorithmen mit Java
ȱ
ȱ
ǻśǰřǼ
ȱǻŚǰřǼ
ǻřǰřǼ
ǻŚǰŘǼ
ȱǻřǰŘǼ
ȱǻřǰŘǼ
ǻřǰŗǼ
ǻřǰȱŖǼ
ȱǻŘǰŗǼ
ȱǻŘǰŘǼ
ǻŘǰŗǼ
ǻŘǰŘǼ
ǻŘǰŗǼ
ȱ
ȱ
ȱ
ǻŗǰŗǼ
ȱǻŗǰŖǼ ǻŗǰȱŗǼ ǻŗǰŖǼ
ǻŗǰŗǼ
ǻŗǰŖǼ
ȱ
ȱȱ£ȱ ȱǰȱȱȱ ȱȱȱȬ
ȱȱȱȱȱȱǯȱ
ȱ
ȱûȱûȱȱȱȱȱȱǰȱ ȱȱȱȱśŖŖȱ ȱ
ǯȱ £ȱ ȱ ȱ ȱ £ ȱ ¢ȱ ǽŖǯǯǾǽŖǯǯǾȱ ǰȱ ȱ ȱ ǽǾǽǾȱ
ȱȱûȱǰȱȱȱȱûȱȱȱȱ ȱȱû£ȱȱ
ǯȱ
ȱ
p[0][0]
p[1][0] p[1][1]
p[2][0] p[2][1] p[2][2]
p[3][0] p[3][1] p[3][2] p[3][3]
....................................
p[m][0]
p[m][1]
p[m][2]
......p[m][m]
Programm 2
import java.io.*;
import java.util.*;
public class P08Oktoberfest2 {
private static final String FileInputName = "oktoberfest.in";
private static final String FileOutputName =
"oktoberfest.out";
private static final int NMAX = 500;
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
float p[][] = new float[2 * NMAX + 1][2 * NMAX + 1];
8 Dynamische Programmierung
p[0][0] = 1;
p[1][0] = p[1][1] = 0.5f;
for (int i = 2; i <= 2 * NMAX - 2; i++) {
p[i][0] = p[i][i] = p[i - 1][0] * 0.5f;
for (int j = 1; j < i; j++)
p[i][j] = 0.5f*p[i-1][j] + 0.5f*p[i-1][j-1];
271
}
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
while (scanner.hasNextInt()) {
int n = scanner.nextInt();
out.printf(Locale.ENGLISH, "%3d: %.4f%n",
n, 1 - p[2 * n - 2][n - 1]);
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
ȱȱ ȱȱȱȱȱ ȱȱ¢ȱǽǾǽǾȱ£ ȱ
ûǰȱȱȱ ȱȱȱȱ§£ȱ£ǯȱȱȱ
ȱȱ£ ȱȱȱ£ȱǰȱûȱãȱȱȱȱ£ȱûȱȱ
ǯȱ ûȱ ȱ ƽȱ śŖŖȱ ȱ ȱ ¢ȱ ǽǾǽǾȱ ŗǯŖŖŘǯŗŖŗȱ ȱ ȱ Ȭ
¢ȱǯȱ ȱȱȱȱŚȱ¢ȱǰȱǯǯȱ ȱȱŚȱȘȱŗǯŖŖŘǯŖŖŗȱƽȱ
ŚǯŖŖŞǯŖŖŚȱ¢ȱǻǯȱřǰşȱǼǯȱȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ £ ȱ
ȱǻȱûȱȱȱȱ§£ȱȱȱûȱȱȱǼǰȱȱ
ȱȱ ǰȱȱȱȱǰȱȱȱȱǻǰȱȦŘǼȱûȱȱȱȬ
ǯȱȱDZȱȱ£ȱđȱ£ ȱǰȱȱȱȱȬ
ȱ ǻǰȱ ȦŘǼȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ
ǻǰȱŖǼǰȱǻǰȱŗǼȱȱǻǰȱǼȱûȱȱȱȱǯȱȱ§ȱȱȱȬ
DZȱȱ
ȱ
Programm 3
import java.io.*;
import java.nio.*;
import java.util.*;
272
Grundlegende Algorithmen mit Java
public class P08Oktoberfest3 {
private static final String FileInputName = "oktoberfest.in";
private static final String FileOutputName =
"oktoberfest.out";
private static final int NMAX = 1001;
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
FloatBuffer a = FloatBuffer.allocate(NMAX);
FloatBuffer c = FloatBuffer.allocate(NMAX);
a.put(0.5f);
a.put(0.5f);
c.put(1);
for (int i = 2; i < NMAX; i++) {
float aux1 = a.get(0);
a.put(0, 0.5f * aux1);
for (int j = 1; j < i; j++) {
float aux2 = a.get(j);
a.put(j, 0.5f * aux1 + 0.5f * aux2);
aux1 = aux2;
}
a.put(a.get(0));
if (0 == i % 2)
c.put(a.get(i / 2));
}
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
while (scanner.hasNextInt()) {
int n = scanner.nextInt();
out.printf(Locale.ENGLISH, "%3d: %.4f%n",
n, 1 - c.get(n - 1));
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
8 Dynamische Programmierung
273
Andere Lösungsmöglichkeit
ȱǰȱȱȱȱȱûȱǻǰȱǼȱȱȱȱûȱȬ
£ȱȱ§ȱǯȱȱãȱȱȱȱ ȱȱȱȱ
ǻŘǰȱǼǰȱȱȱ∈ȱȱǿŖǰȱŗǰȱŘǰȱdzǰȱśŖŖȀǯȱȱ ȱȱû£ȱȱûȱǻŘǰȱǼȱȱ
ȱȱȱDZȱ
ȱ
ŗȱƽȱȱȱȱȱȱŘȱǰȱȱŖȱȱŗȱȱãȱǻŖȱȱŗȱ
ǰȱ ȱ£ ǯȱȱ£ȱǼȱ
ŘȱƽȱȱȱȱȱȱŘȱȱȱȱȱȱȱŖȱȱȱȬ
ȱȱȱȱŗȱǰȱȱȱȱȱȱ£ȱȱȱȱǯȱ
ȱȱȱ ȱȱ£ȱ
M2
ǯȱ
M1
§ 2n ·
«ŗȱ«ȱȱŘŘǯȱȱ«Řȱ«ȱȱȱ §ȱȱ ¨¨ ¸¸ ǯȱ ȱȱDZȱ
©n¹
§ 2n ·
¨¨ ¸¸
n
Tn = © 2 n+1¹ ȱ
2
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱǻŗǼȱ
ȱ
ȱ
ȱ
ȱǻŘǼȱ
ȱ
ȱǻŗǼȱȱȱȱȱȱȱDZȱ
ȱ
Tn =
2n − 1
Tn −1 ȱȱŖȱƽȱŗȱ
2n
ȱ
ȱ
ȱ
ȱ
ȱ ȱȱǻŘǼȱ£ȱ ȱȱȱǯȱ
Programm 4
import java.io.*;
import java.util.*;
public class P08Oktoberfest4 {
private static final String FileInputName = "oktoberfest.in";
private static final String FileOutputName =
"oktoberfest.out";
private static final int NMAX = 501;
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
274
Grundlegende Algorithmen mit Java
float t[] = new float[NMAX];
t[0] = 1f;
for (int i = 1; i < NMAX; i++) {
t[i] = (2f * i - 1.0f) / (2f * i) * t[i - 1];
}
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
while (scanner.hasNextInt()) {
int n = scanner.nextInt();
out.printf(Locale.ENGLISH, "%3d: %.4f%n",
n, 1 - t[n - 1]);
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgaben
ŗǯ
Řǯ
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǵȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ŗȱ
ȱȱȱȱŘȱǵȱ
ȱ ȱ ŗȱ £ȱ ȱ ȱ ȱ ǻǼǰȱ ȱ ȱ ȱ ŗȦŘȱ £ȱ Ȭ
ǯȱȱȱȱȱȱDZȱ
ȱ
double f(int n){
double p = 1d;
for(int i=0; i<n; i++) p*=2;
return 1/p;
}ȱ
ȱ
řǯ
Śǯ
śǯ
ȱȱŘȱȱ ȱȱ¢ǰȱȱȱ ȱȱȱȱȱ
ȱ ȱ £ǯȱ ȱ ȱ ȱ £ ȱ ȱ ȱ
ȱȱȱȱȱǯȱ
ȱȱȱȱ ȱ£ȱ ȱȱ ȱȱȱ
ȱ ȱ ǯȱ £ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ Ȭ
ȱûȱȱȱȱȱȱȱ ǯȱ Ȭ
ȱȱȱȱǰȱȱȱȱ¢ȱ ǯȱ
ȱȱȱȱãǰȱȱȱȱǻŘǼȱ£ǯȱ
8 Dynamische Programmierung
Ŝǯ
ŝǯ
275
§ 2n ·
§ȱǰȱ ȱ«Řȱ«ȱ §ȱȱ ¨¨ ¸¸ ȱǯȱ
©n¹
ȱȱȱ£ȱ£ ȱȱȱȱȬǰȱûȱȱȱȱ
£ǯȱǯȱȱǽŖŜǾȱȱȱãǯȱ
Problem 9. Springer auf dem Schachbrett
ȱ ȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ǯȱȱ ȱȱ ȱȱDZȱ ȱ
ȱ ȱ Ȭȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ
ȱǯȱȱû£ȱȱûȱȱȱ
£ ȱȱȱȱǯȱ
DZȱ ȱǯȱȱȱśȱûȱȱǰȱŗǰȱŗǰȱŘǰȱŘȱ
ȱ ȱ DZȱ ȱ ȱ ȱ Ȭȱ ȱ £ȱ ȱ
ȱ ǻŚȱ ≤ȱ ȱ ≤ȱ ŘŖǼȱ ȱ ŗǰȱ ŗǰȱ Řǰȱ Řȱ ȱ ȱ Ǯ ȃȱ
ȱȬȱȱǯȱ
DZȱ ȱǯȱ ȱ£ȱȱ§ȱȱû£ȱȬ
ȱȱȱȱȱȱǰȱȱȱǯȱȱȱȱȱǰȱ
ȱ ȱȱȱȱȱȱǯȱDZȱ
springer.in
8 1 1 8 7
5 5 2 1 4
15 2 13 14 15
springer.out
Laenge kuerzester Weg: 5
(1, 1)(3, 2)(5, 3)(7, 4)(6, 6)(8, 7)
Laenge kuerzester Weg: 2
(5, 2)(3, 3)(1, 4)
Laenge kuerzester Weg: 6
(2, 13)(4, 14)(6, 15)(8, 14)(10, 15)(12, 14)(14, 15)
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱ£ȱ ȱȱȱ£ȱȱûȱûȱȱǰȱȱ
ȱȱȱ£ȱȱȱ£ȱǯȱȱ ȱȱȱ£ǰȱȱ
ȱȱǰȱ ȱȱ ȱȱȱȱ£ȱȱȱȬ
ȱ£ȱȱ ȱȱ£ǯȱûȱȱ£ ȱȱȱȱȱ
ȱȱDZȱ
ȱ
3
2
1
2
3
2
3
2
3
0
3
2
1
2
3
2
3
4
1
2
3
2
3
2
3
276
Grundlegende Algorithmen mit Java
ȱȱȱȱ ȱ ȱȱȱȱǰȱȱȱȱȱȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ §ȱ £ȱ ǰȱ Ȭ
£ȱ ȱȱDZȱ
ȱ
int table[NMAX][NMAX]; ȦȦȱȱȱȱ£Ȭ
int n;
ȦȦȱȱȱȬȱȱ£ȱȱ
int pred[NMAX*NMAX];
ȦȦȱȱȱ§Ȭǰȱȱȱȱ
ȱ
ȱ ȱȱȱȱǰȱǰȱȱȱȱȬ
ǰȱȱȱȱȱûȱȱȱȱ£ȱȱ§ǯȱȱ
ȱ£ȱǰȱȱ ȱȱ§ȱȱDZȱ
ȱ
- ȱǻǼDZȱȱȱȱȱȱȱ ǯȏȱǻȬ
ȱ ȱ ȱ ǼDzȱ ȱ ȱ ȱ ȱ Ǯȃǰȱ ȱ ȱ
ȱ£ǰȱȱȱȱȱ ǰȱȱǯȱ
- ȱǻǼDZȱȱȱ£ûǰȱ ȱȱȱȱǻǰȱǼȱȱȱȬ
ȱǰȱȱǰȱ ȱȱȱȱǯȱȱ
- ȱ¢ǻǼDZȱȱǰȱȱȱȱȱǯȱȱ
ȱȱȱ ȱȱȱȱȱȱȉȱȱȱȬ
§ǰȱ£ǯȱǯȱûȱȱƽȱśDZȱȱȱ
ȱ
- ȱ ȱ ǻǰȱ Ǽȱ ȱ ȱ ȱ ȱ ȱ
Ŗȱ ŗȱ Řȱ řȱ Śȱ
ȱȱ⋅ȱȱƸȱȱȱ
ȱȱśȱ Ŝȱ ŝȱ Şȱ şȱ
ûȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ŗŖȱ ŗŗȱ ŗŘȱ ŗřȱ ŗŚȱ
ȱȱȱ¡DZȱǻȱȱȱǰȱȱȱȱǼȱ
ŗśȱ ŗŜȱ ŗŝȱ ŗŞȱ ŗşȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ŗȱ
ŘŖȱ Řŗȱ ŘŘȱ Řřȱ ŘŚȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱȱƸȱŗȱȱȱȱȱȱȱƸȱŗȱǻȱȱȬ
ȱȱȱȱŗǷǼȱ
- ȱ ǻǼDZȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
¡ȱǰȱûȱȱȱ£ȱȱȱǯȱûȱȱȱȬ
ȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ȱ ãǰȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
ȱ ȱ ǻȱ £ȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ ûȱ
ȱȱȱȱȱȱȱȱȱ ȱǼǯȱ
ȱ
ȱȱããȱ §ȱȱ ȱȱȱ ǯȱ
ȱ ȱȱ ȱȱȱȱȱǯȱ ȱ£ ȱ
ȱǻǰȱǼȱȱǻǰȱǼȱûȱ ȱȱ ȱǰȱ ȱȱȱǻǰȱǼȱȱȱȱ
ȱȱȱǻǰȱǼȱȱǯȱȱȱȱ ȱãȱȱȱ
8 Dynamische Programmierung
277
ȱ ȱ ȱ ǻȱ Ȯȱ ȱ ȱ Ǽȱ ¢ǯȱ ȱ ȱ ȱ
ûȱȱȱȱȱǯȱȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P09Knight {
private static final String FileInputName = "springer.in";
private static final String FileOutputName = "springer.out";
private int pred[];
private int table[][];
P09Knight(int szTable) {
this.table = new int[szTable][szTable];
for (int[] tLine : this.table) {
Arrays.fill(tLine, Integer.MAX_VALUE);
}
this.pred = new int[szTable * szTable];
}
private boolean onTheTable(int x, int y) {
int szTable = this.table.length;
return x >= 0 && x < szTable && y >= 0 && y < szTable;
}
private static class Position {
int row;
int column;
Position(int row, int column) {
this.row = row;
this.column = column;
}
}
void doMove(int x, int y, int c) {
ArrayList<Position> v = new ArrayList<Position>();
int szTable = this.table.length;
for (int i = -2; i < 3; i++)
for (int j = -2; j < 3; j++)
if (2 == Math.abs(i * j)) {
int xNew = x + i;
int yNew = y + j;
if (onTheTable(xNew, yNew) &&
278
Grundlegende Algorithmen mit Java
this.table[xNew][yNew] > c) {
this.pred[xNew * szTable + yNew] = x * szTable + y;
this.table[xNew][yNew] = c;
v.add(new Position(xNew, yNew));
}
}
Position p;
while (v.size() > 0) {
int lastIdx = v.size() - 1;
p = v.get(lastIdx);
doMove(p.row, p.column, c + 1);
v.remove(lastIdx);
}
}
private void recoverWay(PrintStream out, int k, int c) {
if (c != 0) {
recoverWay(out, pred[k], c - 1);
int szTable = this.table.length;
out.printf("(%d, %d)", k / szTable + 1, k % szTable + 1);
}
}
void writeResult(PrintStream out, int l2, int c2) {
if (this.table[l2][c2] == Integer.MAX_VALUE) {
out.print("keine Loesung");
return;
}
out.print("Laenge kuerzester Weg: ");
out.println(this.table[l2][c2]);
this.recoverWay(out, l2 * this.table.length + c2,
this.table[l2][c2] + 1);
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
int szTable = scanner.nextInt();
int l1 = scanner.nextInt();
int c1 = scanner.nextInt();
int l2 = scanner.nextInt();
int c2 = scanner.nextInt();
8 Dynamische Programmierung
279
l1--; l2--;
c1--; c2--;
P09Knight p = new P09Knight(szTable);
p.doMove(l1, c1, 1);
p.writeResult(out, l2, c2);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
ȱȱȱû£ȱȱȱǰȱ ȱȱȱȱȱȱ
§đȱȱȱȱ£ȱȱǻȱȱȱǼǯȱȱȱ
ȱãȱǰȱȱȱDZȱȱǯȱ
2
5
0
4
1
2
3
6
4
7
1
0
4
8
7
ȱ
3
6
6
ȱȱ£ ȱȱǻƽśȱȱƽşǼȱ
springer1.in
5 5 2 1 4
9 1 3 7 9
8 1 1 8 7
15 14 13 1 2
springer1.out
Laenge kuerzester Weg: 4
(5, 2)(4, 4)(2, 3)(3, 5)(1, 4)
Laenge kuerzester Weg: 8
(1, 3)(2, 5)(1, 7)(2, 9)(4, 8)(2, 7)(3, 9)
(5, 8)(7, 9)
keine Loesung
Laenge kuerzester Weg: 12
(14, 13)(13, 15)(11, 14)(9, 15)(7, 14)(5, 15)
(3, 14)(2, 12)(1, 10)(2, 8)(1, 6)(2, 4)(1, 2)
280
Grundlegende Algorithmen mit Java
Řǯ
řǯ
Śǯ
ãȱ ȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ ãȱ £ȱ
ǵȱȱǰȱ ȱ ȱȱȱȱûȱǰȱȱȱȱûȱ
ȱ ȱ £ȱ ȱ ǻȱ ȱ Ǽȱ ȱ ȱ ȱ
ȱȱǻȱȱŞȬŗŜȱȱȱûȱȱǼǵȱ
ȱȱȱȱȱǰȱȱȱȱȱȱȱȱȱ
ȱ ǰȱ ȱ ȱ ûȱ ȱ ȱ ȱ ¢ȱ ǽŘǾȱ ȱ
ǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ã£ȱ ȱ ȱ
ȱ ȱǯȱ
ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȱ
ǻǼǯȱ ƽśȱ ȱ ȱ ȱ ǻŗǰȱ ŚǼǰȱ ǻŘǰȱ śǼȱ ȱ ǻřǰřǼȱ ȱ ǯȱ ȱ
ȱ§ȱȱ ȱȱȱȱȱȱȱȱãȬ
ȱȱȱûȱȱȱȱǯȱ
ȱȱ
for (i = -2; i < 3; i++)
for (j = -2; j < 3; j++)
if (2 == Math.abs(i * j)) {
int xNew = x + i;
int yNew = y + j;
ȱ
śǯ
£ȱȱǯȱȱȱǰȱ ȱȱȱȱȱȱȬ
£ȱȱ×ȱ9ȱǻŗȱ≤ȱȱ≤ȱŘŖǰȱŗȱ≤ȱȱ≤ȱŘŖǼȱ£ȱǰȱȱȱȱ
ȱȱȱȱãǯȱ
Problem 10. Summen von Produkten
ȱȱûȱȱȱǀȱřŖȱȱŗǰȱŘǰȱǯǯǯǰȱǰȱȱȱȱŗŖŗǰȱǯȱȬ
ȱȱȱȱŗǰȱŘǰȱǯǯǯǰȱǰȱȱDZȱ
ȱ
bi =
¦
ak1 ⋅ ak 2 ⋅ ... ⋅ aki ȱ
1≤ k1 < k 2 <...< k i ≤ n
ȱ
ȱȱûȱȱƽȱřDZȱ
ȱ
b1 = a1 + a2 + a3
b2 = a1 ⋅ a2 + a1 ⋅ a3 + a2 ⋅ a3 ȱ
b3 = a1 ⋅ a2 ⋅ a3
ȱ
ȱȱŗǰȱŘǰȱǯǯǯǰȱȱȱȱȱ¢ȱǯȱ
8 Dynamische Programmierung
281
DZȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ǯȱ DZȱ ȱ ȱ ȱ Ȭ
ǯȱ ȱ ȱ ȱ ŗǰȱ Řǰȱ ǯǯǯǰȱ ȱ ȱ ǻȱ ȱ Ǽǰȱ ȱ ȱ ȱ ȱ
ȱ ȱȱȱȱȱȱDZȱ
prodsum.in
prodsum.out
1 10
8 35
5 50
6 24
8 17
6 105
16 295
14 374
15 168
1
2
3
4
2
1
7
3
4
ǻǰȱȬȱȱȱŗşşşǰȱ£Ǽȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱȱȬȱȱ£ǰȱȱ£ DZȱ
ȱ¡ŗǰȱ¡Řǰȱǯǯǯǰȱ¡ȱȱ£ȱȱ DZȱ
ȱ
x n + cn −1 x n −1 + cn −2 x n−2 + ... + c0 = 0 ȱ
ȱ
ǰȱȱDZȱȱ
ȱ
ȱ
¦ x x x = −c
n −3
ȱ
ȱ
ȱ
ǻŗǼȱ
ȱ
n
x1 + x2 + ... + xn =
¦ x = −c
i
i =1
n −1
n
x1 x2 + x1 x3 + ... + xn −1 xn =
¦x x = c
i
j
i , j =1
i< j
n −2
n
x1 x2 x3 + x1 x2 x4 + ... + xn −2 xn −1 xn =
i
j k
i , j ,k =1
(i< j <k )
ǻŘǼȱ
............................................................
x1 x2 ⋅ ... ⋅ xn = (−1) n c0
ȱ ȱǻŗǼȱȱȱȱȱDZȱ
ȱ
( x − x1 )( x − x2 ) ⋅ ... ⋅ ( x − xn ) = 0 ȱȱȱȱȱ ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ǻřǼȱ
282
Grundlegende Algorithmen mit Java
ȱ ȱǰȱȱȱ£ȱȱ ȱǻřǼȱȱȱ ŗǰȱŘǰȱǯǯǯǰȱȱ
ǰȱȱȱȱȱȬǰȱȱȱȱŗȱȱȬŗȱ£ȱ Ȭ
£ȱȱ ȱǻŗǼȱȱãȱȱȱǯȱȱȱ
ȱ
£ȱȱǯȱȱȱ f = a0 + a1 X + ... + an X n ȱ¢ȱȬȱ ȱǻŖǼǯȱȱ
α1 ,α 2 ,...,α n ȱ£ȱȱȱǰȱȱDZȱ
ȱ
an −1
­
°α1 + α 2 + ... + α n = − a ,
n
°
°
an − 2
°α1α 2 + α1α 3 + ... + α1α n + ... + α n −1α n = a ,
n
°
°
an − 3
,
°α1α 2α 3 + α1α 2α 4 + ... + α n − 2α n −1α n = −
an
°
°
ȱȱȱ
®...
°
a
°α1α 2 ...α k + α1α 2 ...α k −1α k +1 + ... + α n − k +1α n − k + 2 ...α n = (−1) k n − k ,
an
°
°...
°
°
n a0
°α1α 2 ...α n = (−1) a .
n
°
°¯
ȱ
ǻŚǼȱ
ȱ ǰȱ ȱ ȱ ¡ȱ ȱ α1 ,α 2 ,...,α n ȱ £ȱ ȱ ¢ȱ ȱ
ǰȱ ȱȱȱȱǻŚǼȱûǯȱ
ȱ
ȱ £ȱ ȱ ¢ȱ ȱ ǻŗǼȱ ȱ ȱ ǰȱ ȱ ǽǾȱ ƽȱ ȱ
ûȱȱȱƽȱŖǰȱŗǰȱdzǰȱǯȱ ȱȬȱȱ£ȱȱȱȱ¢ȱȱȱ
¢ȱǻ −ȱȱǼǯȱȱ¢ȱȱȱ−ȱŗǰȱ ȱȱ DZȱ
ȱ
ǽŖǾȱƽȱ−ȱǽŖǾDzȱ
ȱȱȱ
ȱ
ǽŗǾȱƽȱŗDzȱ
ȱ
ûȱȱȱȱŗȱȱ−ŗȱȱ ȱȱȱDZȱ
ȱ
ǻ−ǽǾǼǻǽŖǾȱƸȱǽŗǾȱƸȱǯǯǯǯȱƸȱǽ−ŗǾȬŗȱƸȱǽǾǼȱ
ȱ
ȱ
ȱ
ǻśǼȱ
ȱ
ȱȱȱ ȱ ǽǾȱȱȱȱ ȱ £ȱȱ¢ȱ
ȱǻŚǼDZȱ
ȱ
8 Dynamische Programmierung
283
ǽŖǾȱȱȱȱȱÅȱ−ǽŖǾȘǽǾȱ
ȱ
ǽǾȱȱȱȱȱȱÅȱȱǽ−ŗǾȮǽǾȘǽǾȱûȱȱȱȱŗȱȱȱ ȱ
ȱ
ȱ
ǻŜǼȱ
ȱ
ǽƸŗǾȱÅȱȱǽǾȱ
ȱ
ȱ ȱ £ȱ §đȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǰȱ ȱ
ȱȱŗǰȱŘǰȱǯǯǯǰȱȱȱǻ−ŗǼǽǾǰȱȱǻ−ŗǼȬŗǽȬŗǾǰȱǯǯǯǰȱǽŖǾȱǯȱȱ
ȱ ȱȱȱ¢ȱǽǾȱDZȱ
j = 1;
if (szArr % 2 != 0)
j = -1;
for (k = 0; k <= szArr; k++) {
arr[k] = j * p[k];
j *= -1;
}
ȱ
đȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱǻǼǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P10SumsOfProducts {
private static final String FileInputName = "prodsum.in";
private static final String FileOutputName = "prodsum.out";
private int szArr;
private long[] arr;
P10SumsOfProducts(int szArr, long[] arr) {
this.szArr = szArr;
this.arr = arr;
}
private int sumDigits(long nr) {
int s = 0;
while (nr != 0) {
s += nr % 10;
nr /= 10;
}
return s;
}
void write(PrintStream out) {
for (int i = szArr - 1; i >= 0; i--) {
284
Grundlegende Algorithmen mit Java
out.print(sumDigits(arr[i]));
out.print(' ');
out.println(arr[i]);
}
}
void process() {
int j, k;
long p[] = new long[szArr + 1];
long q[] = new long[szArr + 1];
p[0] = -arr[0];
p[1] = 1;
for (k = 1; k < szArr; k++) {
q[0] = (-1) * p[0] * arr[k];
for (j = 1; j <= k; j++) {
q[j] = p[j - 1] - p[j] * arr[k];
}
q[k + 1] = p[k];
for (j = 0; j <= k + 1; j++)
p[j] = q[j];
}
j = 1;
if (szArr % 2 != 0)
j = -1;
for (k = 0; k <= szArr; k++) {
arr[k] = j * p[k];
j *= -1;
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
List<Long> list = new ArrayList<Long>();
while (scanner.hasNextLong()) {
list.add( scanner.nextLong() );
}
long arr[] = new long[list.size()+1];
for(int i=0; i<list.size(); i++)
arr[i] = list.get(i);
if (arr.length == 0) {
return;
}
out = new PrintStream(new File(FileOutputName));
8 Dynamische Programmierung
285
P10SumsOfProducts p =
new P10SumsOfProducts(list.size(), arr);
p.process();
p.write(out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
Śǯ
ȱȱ¢ȱ ǰȱȱȱȱȱ£ȱǯȱ
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ǯǯ¢ȱ £ȱ ǰȱ
ȱ£ȱȱȱ¢ǯȱ
ȱǰȱȱȱȱŗǰȱŘǰȱǯǯǯǰȱȱȱȱǰȱ§ǯȱ ȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ãđȱ ȱ ȱ
ǯ ȱȱûȱȱ ȱǯǯ ǯȱ
ȱȱȱ £ȱȱǻŜǼȱȱȱȱȱȱ
¢ȱǰȱ ȱȱȱȱȱǽƸŗǾǰȱǽǾǰȱdzǰȱǽŖǾȱȱ
ǯȱȱȱȱǰȱȱ£ ȱŘȱ¢ȱȬȱȱȬ
ȱ ǯȱȱȱȱȱȱǻǼǯȱ
ȱ ȱ ȱ Ȭȱ §ȱ ǰȱ ȱ ȱ ȱ ȱ ¢Ȭ
ȱ£ ȱ ȱȱǻ f = a0 + a1 X + a2 X 2 Ǽȱȱȱȱ¢ȱȱ
ȱǻ f = a0 + a1 X + a2 X 2 + a3 X 3 Ǽǯȱ
śǯ
ȱ ȱ ȱ ¢ȱ f = X 3 − 10 X 2 + 29 X − 20 ǯȱ ȱ ȱ ȱ
ȱżŗǰȱżŘȱȱżřȱȱ¢ǰȱ ȱDZȱ α1 + α 2 = α 3 ǯȱȱ
Ŝǯ
ȱȱƆȱȱȱ 2 x 3 − 4 x 2 − 7 x + λ = 0 ǰȱ ȱȱ đǰȱȱ
ȱ£ ȱȱȱȱŗȱǯȱ
ŝǯ
ȱȱȱ ȱ x 3 + ax 2 + bx + c = 0 ȱȱȱȱżŗǰȱżŘȱȱżřȱ Ȭ
ǯȱȱȱ£ ȱ ȱȱȱȱŽŗǰȱŽŘǰȱȱŽřǰȱȱ
DZȱ
Ǽȱ β1 = 3α1 + α 2 + α 3 ǰ β 2 = 3α 2 + α1 + α 3 ǰȱ β3 = 3α 3 + α1 + α 2 ȱ
1
1
1
Ǽȱ β1 = α1 ǰ β 2 = α 2 ǰ β3 = α 3 ȱ
2
2
2
c) β1 = −α1 + α 2 + α 3 , β 2 = −α 2 + α1 + α 3 , β3 = −α 3 + α1 + α 2 .
286
Grundlegende Algorithmen mit Java
Problem 11. Minimale Triangulierung eines konvexen Vielecks
ȱ¡ȱȱȱȱ¢ǰȱȱȱȱ ȱȱȱŗŞŖ°ȱǻȱȬ
đDZȱπǼȱǯȱȱȱȱ¡ȱȱȱȱȱȱ
ȱȱȱȱȱǯȱȱ£ȱȱȱ
ûȱȱ¡ȱǻƸŘǼȬȱȱȱȬȱȬDZȱ Cn = 1 §¨ 2n ·¸ ǯȱȱ
¨ ¸
n +1© n ¹
ȱ
Śȱ ȱÆȱŘȱãȬ
ȱ
śȱ ȱÆȱśȱãȬ
ȱ
Ŝȱ ȱ Æȱ ŗŚȱ ãȬ
ȱ
ȱ
ȱȱȱȱȱȱȱǰȱȱȱȱȱȱȬ
§ȱ ȱ ȱ ȱ ȱ ȱ ǻȱ Ǽǯȱ DZȱ ȱ
ȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ £Ȭȱ ȱ ȱ ȱ ǯȱ DZȱ ȱ ǯȱ ȱ ȱ
ȱȱȱȱȱȱ§ȱȱȱȱȱȱȱ
ȱǻȱȱȱ £ȱȱǼǰȱȱȱȱȱǯȱ
DZȱ
ȱ
triang.in
-4 -9
2 -9
8 8
-1 11
-8 8
-8 -5ȱ
triang.out
Kleinste Umfangssumme = 152.8
bei Triangulierung:
0 1 5
1 4 5
1 2 4
2 3 4ȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱ ȱ ȱ Ŗǰȱ ŗǰȱ Řǰȱ dzǰȱ Ȭŗȱ ȱ ȱ ȱ ¢ǯȱ ȱ §ȱ ȱ
ãȱȱ ȱȱ ǻǰȱǰȱǼȱǰȱ ȱǰȱȱȱȱȱ ȱ
ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ §ȱ ȱ ǰȱ ȱ ȱ
8 Dynamische Programmierung
287
ȱȱǰȱȱȱ ȱǯȱȱ£ȱ ȱȱǽǾǽǾǰȱȱ
Ŗȱ ≤ȱȱǀȱȱ ≤ȱȬŗǰȱȱ ȱȱȱȱûȱȱ¢ȱȱȱ
ȱǰȱƸŗǰȱƸŘǰȱdzǰȱǯȱȱ ȱûȱȱȱȱȱǽŖǾǽȬŗǾǯȱȱ
ȱ
ȱ
ȱ ȱ ȱ ȱ ûȱ ȱ ȱ Ȭ
ŗ
ȱûȱȱ¢ȱȱȱȱǰȱƸŗǰȱ
ƸŘǰȱ dzǰȱ ȱ ȱ ȱ ȱ ȱ ȱ
Ŗ
ȱȱȱȱȱǀǀǰȱȱȱȱȱ
ȱDZȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱǻǽǾǽǾǼƸǻǽǾǽǾǼƸ ǻǰȱǰȱǼȱȱ
ȱ
ǻȱ ȱ ȱ ȱ ȱ
∆Ǽǯȱȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ¢ȱ ȱ ȱ
ǯȱȱ ȱ ȱȱ¢ȱȱȱ£ȱȱȱ
ȱ ȱ ¢ȱ ȱ ȱ £ȱ ȱ ǻȱ ȱ £ȱ ¢Ǽǯȱ ûȱ
ȱ¢ǰȱȱȱȱȬȱȱȱȱȱǰȱȱȱ ȱȱ
ȱȱȱDZȱ
ȱ
­°0 für k = i + 1
C[i ][k ] = ®min{C[i][ j ] + C[ j ][k ] + w(i, j, k )} für k > i + 1 ȱ
°̄ i< j<k
ȱ
ȱ
ȱǻŗǼȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻǼȱ ȱ ȱ ȱ ǽǾǽǾȱ
ûȱȱǰȱȱȱŖȱ ≤ȱȱǀȱȱ ≤ȱȬŗǯȱȱȱȱȱ ȱãȱ ȱ
ȱȱȱûȱȱ ȱȱ¢ȱǻǽǾǽǾȱȱǀǼǰȱ ȱ Ȭ
ȱ ȱȱȱȱ ǰȱȱȱȱȱ£ȱȱȬ
ȱ £ȱ ǯȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ
ȱȱȱȱǯȱ
ȱ
ȏȏ ȱ ȱ
ȱȱȱ
ȱ
ȱȱȱȱǻƽŗDzȱǀDzȱȱŗǼȱ¡ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȦȦȱȱ§ȱ¢
ȱ
ȱȱȱȱȱȱȱȱȱǻȱȱǻǰȱǼ←ǻŖǰȱǼǰǻŗǰȱƸŗǼǰdzǰȱǻȬȬŗǰȬŗǼǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱ
ȱȏ ȏȏŗǻǽǾǽǾǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱ←ȱǰȱǯǯȱǽǾǽǾƽ min {C [ i ][ j ] + C [ j ][ k ] + w ( i , j , k )} ȱ
ȱ
i < j< k
ȱ
ȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱȏȱ
ȱ
ȏȱ ȏȏ ȱ
ȱ
288
Grundlegende Algorithmen mit Java
ȱȱǰȱȱȱȱȱDZȱ
ȱ
ȱ
ȏǻǰȱȱǼȱ
ȱ
ȱȱȱȱ ȱǻȱȬǁŗȱǼȱȱ
ȱ
ȱȱȱȱȱȱȱȱƜȱǽǾǽǾȱ
ȱ
ȱȱȱȱȱȱȱȏǻǰȱǰȱǼȱȱ
ȱȱ
ȱ
ȱȱȱȱȱȱȱȏǻǰȱǼȱ
ȱ
ȱȱȱȱȱȱȱȏǻǰȱǼȱ
ȱ
ȱȱȱȱȏ ȱ
ȱ
ȏȏǻǰȱǼȱ
ȱ
ȱ
ȱŗǻ¡ŗǰȱ¢ŗǼȱȱŘǻ¡Řǰȱ¢ŘǼȱ£ ȱȱȱȱȱǰȱȱȱȱDZȱ
P1 P2 = ( x1 − x2 ) 2 + ( y1 − y2 ) 2 ǯȱȱȱȱȱȱȱǻǼȱǯȱ
ȱȱǻǼȱȱȱȱȱȱȱ ȱȱȬ
ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ Ȭ
ȱ ǰȱ ȱ ȱ ȱ ǻǼȱ ȱ ¡ȱ
ȱȱãȱ§ȱȱûȱȱȱ£ȱȱȱ ȱ
£DZȱǻŖǰȱŗǰȱŘǼǰȱǻŖǰȱŗǰȱřǼǰȱdzǰȱǻȬřǰȱȬŘǰȱȬŗǼǯȱȱȱǻǼȱȱȱȱȱ
ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻŖǰȱ Ŗǰȱ ŖǼȱ ȱ ǰȱ
ûȱ ȱ ǰȱ ȱ ȱȱ ǻǰȱǰȱǼȱȱŖȱ ≤ȱ ȱ ǀȱȱǀȱȱ ¡ǰȱȱ¡Ȭ
ȱȱȱǻŖǰȱŖǰȱŖǼȱǰȱȱȱǻŖǰȱŖǰȱŖǼȱȱȱ ȱǯȱȱ£ȱȬ
ȱȱȱȱȱȱȱȱȱǀȱŖȱ ££ûȱȱȱȱƽŖȱȱǀŖȱ
ȱȱȱȱƽŖǰȱƽŖȱȱǀŖDZȱ
ȱ
⏐ǿǻǰȱǰȱǼȱȩȱȱǀȱŖȀ⏐ȱƸȱ⏐ǿǻǰȱǰȱǼȱȩȱŖȱƽȱǰȱȱǀȱŖȀ⏐ȱƸȱ⏐ǿǻǰȱǰȱǼȱȩȱŖȱƽȱǰȱŖȱƽȱǰȱȱǀȱŖȀ⏐ȱ
ȱ
ûȱȱȱ ǀŖȱȱȱ §¨ n − i − 1·¸ ȱȱȱǻȱȱȱ£ȱȱȱǻǰȱǼȱ
¨
©
2
¸
¹
ȱŖȱ ≤ȱȱǀȱȱǀȱȱǀȱȱǰȱȱđȱȱȱǻǰȱǼȱȱȱǀȱȱȱȱȱǿŖƸŗǰȱŖƸŘǰȱdzǰȱȬ
ŗȀǼǯȱûȱƽŖȱ ȱȱȱŖȱȱȱȬŖȬŗȱȱǻ§ȱûȱƽŖƸŗǰȱŖƸŘǰȱdzǰȱȬŗǼǯȱ
ûȱƽŖǰȱƽŖȱȱǀŖȱȱȱŖȬŖȬŗȱǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P11ConvexPolygonMinimalTriangulation {
private static final String FileInputName = "triang.in";
8 Dynamische Programmierung
289
private static final String FileOutputName = "triang.out";
private List<Point> vP;
private List<Double> w;
private double c[][];
private static class Point {
double x;
double y;
Point(double x, double y) {
this.x = x;
this.y = y;
}
P1 P2 = ( x1 − x2 ) 2 + ( y1 − y2 ) 2
double dist(Point p) {
return Math.sqrt(Math.pow(this.x - p.x, 2)
+ Math.pow(this.y - p.y, 2));
}
}
static double perimeter(Point p1, Point p2, Point p3) {
return p1.dist(p2) + p2.dist(p3) + p3.dist(p1);
}
P11ConvexPolygonMinimalTriangulation(List<Point> vPoints) {
this.vP = vPoints;
this.w = new ArrayList<Double>();
int szVP = vP.size();
for (int i = 0; i < szVP - 2; i++)
for (int j = i + 1; j < szVP - 1; j++)
for (int k = j + 1; k < szVP; k++) {
this.w.add(perimeter(vP.get(i), vP.get(j),
vP.get(k)));
}
this.c = new double[szVP][szVP];
}
private double getW(int i0, int j0, int k0) {
int n = this.vP.size();
ȱãȱȱûȱȱ¡ȱ
int p = 0;
ȱȱDZȱ
for (int i = 0; i < i0; i++){
int p=0;
p += (n-i-1)*(n-i-2)/2;
int i2, j2, k2;
}
for(i2=0; i2<i0; i2++)
for (int j=i0+1; j<j0; j++){
for(j2=i2+1; j2<n-1; j2++)
for(k2=j2+1; k2<n;k2++) p++;
p += n-j-1;
for(j2=i0+1; j2<j0; j2++)
}
for(k2=j2+1; k2<n; k2++) p++;
p += k0-j0-1;
p+=k0-j0-1;
return w.get(p);
return w[p];
290
Grundlegende Algorithmen mit Java
}
void doProcess() {
int szVP = this.vP.size();
for (int p = 1; p < szVP; p++) {
for (int i = 0; i < szVP - p; i++) {
int k = i + p;
if (1 == p)
c[i][k] = 0;
else {
int j = i + 1;
c[i][k] = c[i][j] + c[j][k] + getW(i, j, k);
c[k][i] = j;
for (j = i + 2; j < k; j++) {
double val = c[i][j] + c[j][k] + getW(i, j, k);
if (val < c[i][k]) {
c[i][k] = val;
c[k][i] = j;
}
}
}
}
}
}
private void writeTriang(PrintStream out, int i, int j) {
if ((j - i) > 1) {
int k = (int) c[j][i];
out.printf(" %d %d %d%n", i, k, j);
writeTriang(out, i, k);
writeTriang(out, k, j);
}
}
void write(PrintStream out) {
int idx = vP.size() - 1;
out.printf(Locale.ENGLISH,
" Kleinste Umfangssumme = %.4f%n bei Triangulierung: %n",
c[0][idx]);
writeTriang(out, 0, idx);
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
8 Dynamische Programmierung
291
List<Point> vPoints = new ArrayList<Point>();
while (scanner.hasNextDouble()) {
double x = scanner.nextDouble();
double y = scanner.nextDouble();
vPoints.add(new Point(x, y));
}
P11ConvexPolygonMinimalTriangulation p10 =
new P11ConvexPolygonMinimalTriangulation(vPoints);
p10.doProcess();
out = new PrintStream(new File(FileOutputName));
p10.write(out);
ŗǯ ȱȱǻǼȱ
} finally {
Řǯ ȱ§ȱǻǰȱ Ǽȱ
if (scanner != null) {
řǯ
ȱǽǾǽǾȱȱȱȱ ǰȱȱ
scanner.close();
Śǯ ȱǽŖǾǽȬŗǾȱ
}
śǯ ȱȱȱ
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱȱȱȱȱǰȱȱȱȱȱȱȱ
ǰȱȱȱȱ§ȱȱȱȱǰȱȱȱȬ
ǰȱȱȱȱǰȱȱȱȱǰȱȱǯȱ
ȱǰȱȱȱ¡£ȱȱûȱǻŖǰȱŖǰȱŖǼȱȱDZȱ ȱ
§ n − 1· § n − i0 − 1· § n − j0 − 1· § n − k 0 − 1·
¸¸ + ¨¨
¸¸ + ¨¨
¸¸ + ¨¨
¸¸ ȱ
getW (i0 , j0 , k 0 ) = ¨¨
3
2
1
© 3 ¹ ©
¹ ©
¹ ©
¹
řǯ
ȱȱ£ȱ ȱȱȱ ǻǼȱȱǻǼȱȱ ȱ
ǯǯȱ ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ Ȭȱ ȱ Ȭ
ȱȱ ȱȱȱȱȱȱǰȱȱ
ȱȱȱ£DZȱȱǻǻǼǰȱǻǼǰȱǻǼǰȱǻǼǰȱǻǼǰȱ
ǻǼǼǰȱ ȱ ȱ ¡ȱ ǻǻǼǰȱ ¡ǻǼǼǰȱȱ ǻ¡ǻǼǰȱ
ǻǼǰȱ ǻǼǰȱǻǼǼǰȱȱȱȱǻǻǼǰȱǻǼǰȱǻǼǰȱǻǼǼǯȱ
Problem 12. Multiplikation einer Matrizenfolge
ȱ £ ȱ £ȱ ȱ ȱ ȱ ȱ £ȱ £ȱ ãǰȱ ȱ ȱ ȱ ȱ
ȱǰȱ ȱȱȱǯȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱǰȱȱȱȱȉȱȱȱȱȱȱǯȱȱȱȱȱȬ
ȱȱȉȱȱȉȱȱȱǯȱ
292
Grundlegende Algorithmen mit Java
ȱȱȱãȱȱȱ ȱǻǰȱǰȱȱzWǿŖȀǼDZȱ
ȱ
§ a11 a12 ... a1n ·
§ b11 b12 ... b1 p ·
¨
¸
¸
¨
¨ a 21 a 22 ... a 2 n ¸
¨ b21 b22 ... b2 p ¸ ȱ
A=¨
, B=¨
... ... ... ... ¸
...
... ... ... ¸
¸
¨
¨
¸
¨a
¸
¨ bn1 bn 2 ... bnp ¸
© m1 a m 2 ... a mn ¹
¹
©
ȱ
ȱȱȱ¡ȱȱƽȱ⋅ȱȱȱDZȱ
ȱ
§ c11
¨
¨ c 21
C =¨
...
¨
¨ c m1
©
c12
c22
...
cm 2
... c1 p ·
¸
... c2 p ¸
ȱ
... ... ¸
¸
... cmp ¸¹
n
ȱȱƽȱŗȘŗƸŘȘŘƸdzƸȘȱƽȱ
¦ a ⋅ b ȱûȱȱȱ∈ǿŗǰdzǰȱȀǰȱ∈ǿŗǰdzǰȱȀǯȱȱ
ik
kj
k =1
ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ȉȱ ȱ ȉȱ ȱ ȱ ȱ ûȱ ǻȱ
ȱȱûȱȱȱȱȱŗȱ ≤ȱȱ ≤ȱǰȱŗȱ ≤ȱȱ ≤ȱǼǯȱȱȱȬ
£ȱŖŗdzȱ£ȱ£ȱãǰȱȱȱǰȱȱȱ¡ȱȱ
ûȱȱȱȱŖȱȱȱǀȱȱȱȱȱǰȱ ȱƸŗȱȱǰȱûȱDZȱȱȱȱ
ȱȱ
£ȏȱǻǼƽ£ȏǻƸŗǼȱûȱȱ∈ǿŖǰȱdzǰȱȬŗȀȱ
ȱȱ Cn =
1 § 2n ·
¨ ¸ ȱãȱ ȱûȱȱȱŖŗdzǰȱ ȱȱ
n + 1 ¨© n ¸¹
ȱȬȱȬȱǯȱȱȱȱȱȱ£ȱȱãǰȱƸŗȱȬ
ȱȱȱȱ£ȱ£DZȱ
ȱ
ȱǻȱǼǰȱǻȱǼȱȱ
řȱȱ→ȱŘȱãȱ
ȱǻȱǻȱǼǼǰȱȱǻǻȱǼȱǼǰȱȱ
ȱ
ǻȱǼȱǻȱǼǰȱǻȱǻȱǼǼȱȱ
Śȱȱ→ȱȱśȱãȱ
ǻǻȱǼȱǼȱȱ
ȱ
ȱ
ȱǻȱǻȱǻȱǼǼǼǰȱȱǻȱǻǻȱǼȱǼǼȱ
ȱ
ȱǻǻȱǼȱǻȱǼǼǰȱȱǻǻȱǻȱǼǼȱǼȱ
ȱ
ȱǻǻǻȱǼȱǼȱǼǰȱǻȱǼȱǻȱǻȱǼǼȱ
śȱȱ→ȱȱŗŚȱãȱ
ǻȱǼȱǻǻȱǼȱǼǰȱǻȱǻȱǼǼȱǻȱǼȱ
ǻȱǻȱǻȱǼǼǼǰȱǻȱǻǻȱǼȱǼǼȱȱ
ȱ
ǻǻȱǼȱǼȱǻȱǼǰȱǻǻȱǼȱǻȱǼǼȱȱ
ǻǻȱǻȱǼǼȱǼȱǰȱǻǻǻȱǼȱǼȱǼȱȱ
8 Dynamische Programmierung
293
ȱȱȱȱDZȱŖȱƽȱŗǰȱŗȱƽȱŗǰȱŘȱƽȱŘǰȱřȱƽȱśǰȱŚȱƽȱŗŚǰȱśȱƽȱŚŘǰȱŜȱƽȱŗřŘǰȱŝȱƽȱ
ŚŘşǰȱŞȱƽȱŗŚřŖǰȱşȱƽȱŚŞŜŘǰȱŗŖȱƽȱŗŜŝşŜǰȱŗŗȱƽȱśŞŝŞŜǰȱdzȱ
ȱ
ȱ£ȱȱǻǰȱǼȱȱ¡ȱȱȱȱȱ ȱǯȱȱ ȱ£ȱ
ȱȱ£ȱŖǻŚŖǰȱřŖǼǰȱŗǻřŖǰȱŗŖǼȱȱŘǻŗŖǰȱŘǼȱǰȱȱȱ£ ȱãȬ
ǰȱȱȱŖŗŘȱ£ȱDZȱ
ǻŖŗǼŘȱȮȱãȱȱŚŖȉřŖȉŗŖȱƸȱŚŖȉŗŖȉŘȱƽȱŗŘŞŖŖȱȱDzȱ
ŖǻŗŘǼȱ Ȯȱ ȱ ȱ ŚŖȉřŖȉŘȱ Ƹȱ řŖȉŗŖȉŘȱ ƽȱ řŖŖŖȱ ȱ ǰȱ
ȱȱŘřǰŚŚȱ£ȱȱŗŘŞŖŖǯȱȱȱ£ȱȱ£ȱ §ǰȱȱãȬ
ȱȱ£ȱ£ ȱȱȱãȱȱ ǯȱȱ
ûȱ ȱ ȱ ȱ ȱ ȱ Şȱ £ȱ ȱ ȱ ŝȱ ƽȱ ŚŘşȱ ãǯȱ
ȱ ȱ ȱ £ȱ ŖǻřŚǰȱ ŘřǼǰȱ ŗǻŘřǰȱ ŗŘǼǰȱ ŘǻŗŘǰȱ ŘǼǰȱ řǻŘǰȱ śǼǰȱ Śǻśǰȱ ŞŖǼǰȱ śǻŞŖǰȱ řǼǰȱ
ŜǻřǰȱřǼǰȱŝǻřǰȱŗŘǼȱǰȱȱãȱȱȱŖŗdzŝȱȱȱ Ȭ
DZȱ
ȱ
ǻŖǻŗǻǻŘřǼŚǼǼǼǻǻśŜǼŝǼȱȮȱãȱŗŘśŞŖŖȱȱDzȱ
ǻŖǻŗŘǼǼǻǻǻřǻŚśǼǼŜǼŝǼȱȮȱãȱŚŘśŘȱȱǰȱȱȱřǰřŞȱȱ
£ȱȱ£ȱûȱȱȱ Ƿȱȱ
ȱ
ȱȱȱȱȱȱȱȱ ȱȱ£ǰȱǯǯȱ
ȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ £ȱ ȱ ȱ ȱ
ȱǯȱ
DZȱ ȱ ȱ ȱ ¡ǯȱ ȱ ȱ ȱ ȱ ȱ £ǰȱ
§ȱȱȱǻ£ȏǰȱ£ȏǼȱȱȱǯȱȱȱ¡ȱŗŖŖȱ
£ǰȱȱȱ£ȱ ȱȱȱȱȱȱȱ
¢ȱǯȱ
DZȱ ȱȱȱ¡ǯȱȱȱȱ£ȱȱȱȬ
ȱ ǰȱȱȱȱȱ ǯȱDZȱ
ȱ
matrix.in
matrix.out
minimal = 4252
34 23
(A0(A1A2))(((A3(A4A5))A6)A7)
23 12
12 2
2 5
5 80
80 3
3 3
3 12
294
Grundlegende Algorithmen mit Java
Problemanalyse und Entwurf der Lösung
ȱȱȱ£ȱŖǰȱŗǰȱdzǰȱȱǰȱȱȱȬȱȱ£ȱȱ
¡ȱȱȱ ȱȱȱȱƸŗǯȱȱȱȱȱǻǰȱǼȱǰȱȱȱȬ
ȱ£ȱȱȱȱûȱȱȱȱƸŗdzȱ§Ȭ
ǯȱȱȱ DZȱ
ȱ
ǻǰȱǼȱƽȱŖȱûȱȱƽŖǰȱdzǰȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱǻŗǼȱ
ǻǰȱƸŗǼȱƽȱȱȉȱƸŗȱȉȱƸŘȱûȱȱƽŖǰȱdzǰȱȬŗȱ ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱȱȱǻŘǼȱ
ȱ
ȱȱȱȱǻřǼȱ
C (i, j ) = min(C (i, k ) + C ( k + 1, j ) + d i ⋅ d k +1 ⋅ d j +1 ) ȱûȱŖȱ≤ȱȱǀȱȱ≤ȱȬŗȱȱȱ
i≤ k < j
ȱ
ǻǰȱ Ǽȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ
Ƹŗǯǯǯȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ ȱ ȱ ȱ Ƹŗȱ ǯȱ ǻƸŗǰȱ Ǽȱ ȱ ȱ
ȱ£ȱȱȱȱȱȱƸŗƸŘdzǯȱȱȬ
ȱȱȱ¡ȱȱƸŗȱȱȱƸŗȱǯȱȱȱȱȬ£ȱ
£ȱ£ǰȱȱȱȱȱȱȉȱƸŗȱȉȱƸŗȱȱǯȱȱ
ȱ ȱȱȱǻǰȱǼȱȱûȱ£ȱȱ§ȱŘǰȱřǰȱdzǰȱȱȬ
ǯȱȱȱȱǻǰȱǼȱȱȱȱȱ ȱȱ£ Ȭ
ȱ ¢ȱ ǽǾǽǾȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ
ȱȱȱ ȱ£ȱûǯȱȱ ȱȱ ȱǻŗǼǰȱǻŘǼȱ
ȱǻřǼȱȱ ȱȱȱǻǼǰȱȱȱ£ ȱ¢ȱǽǾǽǾȱ
ûǯȱȱȱȱȱȱȱ£ȱǰȱȱãȱȱȱ
ȱ ǽŖǾǽȬŗǾȱ ȱ ǯȱ ȱ ȱ ȱ ȱ
£ȱ ǰȱ ȱ ȱ ȱ ȱ ǻǼǰȱ ȱ ȱ ¢ȱ ǽǾȱ
ȱǽǾȱȱȱȱDZȱ
ǽǾȱȮȱ£ȱãȱ ȱȱȱ¡ȱȱ
ǽǾȱȮȱ£ȱđȱ ȱȱȱ¡ȱȱ
ûȱȱȱȱǻǰȱǼȱ ȱȱȱȱȱȱȱǻřǼȱȱǽǾǽǾȱ
ǯȱȱđǰȱȱȱ£ȱdzȱȱƸŗdzȱȱȱ Ȭ
DZȱ
int k = (int) c[j][i];
if (i != k) {
op[i]++;
cl[k]++;
}
if (k + 1 != j) {
op[k + 1]++;
cl[j]++;
}
ȱȱ ȱ ȱȱȱDZȱ
8 Dynamische Programmierung
295
ȱ
constructOrder(i, k);
constructOrder(k + 1, j);
ȱ
ȱ ȱ ȱ ȱ
ȱǯ
ȱ ȱ ¢ȱ ǽǾȱ ȱ ǽǾȱ ȱ ȱȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P12MatrixSequenceMultiplication {
private static final String FileInputName = "matrix.in";
private static final String FileOutputName = "matrix.out";
private int d[];
private int op[], cl[];
private long c[][];
P12MatrixSequenceMultiplication(int[] d) {
this.d = d;
int szD = d.length;
this.op = new int[szD];
this.cl = new int[szD];
this.c = new long[szD][szD];
}
void doProcess() {
int n = d.length - 1;
int i, j, k, p;
for (j = 0; j < n; j++) {
for (i = 0; i < j; i++)
c[i][j] = Long.MAX_VALUE;
c[j][j] = 0;
}
for (p = 1; p < n; p++)
for (i = 0, j = p; j < n; i++, j++)
for (k = i; k < j; k++) {
long aux =
c[i][k] + c[k+1][j] + d[i]*d[k+1]*d[j+1];
if (c[i][j] > aux) {
c[i][j] = aux;
c[j][i] = k;
}
}
296
Grundlegende Algorithmen mit Java
}
private void constructOrder(int i, int j) {
if ((j - i) > 1) {
int k = (int) c[j][i];
if (i != k) {
op[i]++;
cl[k]++;
}
if (k + 1 != j) {
op[k + 1]++;
cl[j]++;
}
constructOrder(i, k);
constructOrder(k + 1, j);
}
}
void write(PrintStream out) {
int n = d.length - 1;
out.printf("minimal = %d%n", c[0][n - 1]);
constructOrder(0, n - 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < op[i]; j++)
out.print('(');
out.print('A');
out.print(i);
for (int j = 0; j < cl[i]; j++)
out.print(')');
}
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
List<Integer> list = new ArrayList<Integer>();
while (scanner.hasNextInt()) {
int i = scanner.nextInt();
int j = scanner.nextInt();
int szD = list.size();
if (szD == 0) {
list.add(i);
} else if (list.get(szD - 1).intValue() != i) {
throw new IOException("Ungueltige Eingabedaten!");
8 Dynamische Programmierung
297
}
list.add(j);
}
int arr[] = new int[list.size()];
for (int k = 0; k < list.size(); k++)
arr[k] = list.get(k);
P12MatrixSequenceMultiplication p =
new P12MatrixSequenceMultiplication(arr);
p.doProcess();
out = new PrintStream(new File(FileOutputName));
p.write(out);
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
Aufgabe
ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ¡ȱ ȱ Ȭ
ȱ ǯȱȱȱȱ ȱ£ȱȱȱŘȱȱȬ
ȱǰȱȱȱȱ ȱȱȱ£ȱ¡ȱǯȱ
ȱ
matrix.in
34 23
23 12
12 2
2 5
5 80
80 3
3 3
3 12
matrix.out
minimal = 4252
(A0(A1A2))(((A3(A4A5))A6)A7)
maximal = 125800
(A0(A1((A2A3)A4)))((A5A6)A7)
3.38 %
Problem 13. Edit-Distanz
ȱȱȱȱȱǻǼȱȱȱǯȱȱȱȱ
ȱȱ§ȱǻǼȱǰȱȱ ȱȱȱȱ
298
Grundlegende Algorithmen mit Java
ȱȱǻȱǼǯȱȱȱDZȱ)ȱȱ →ȱ[ȱȱȱȱ
ǰȱ ȱȱȱȱûȱDZȱ
ȱ
ǻŗǼȱǻ¡ǰȱ¢Ǽȱ≥ȱŖȱûȱȱ¡ǰȱ¢∈ȱǰȱǻ¡ǰȱ¢ǼȱƽȱŖȱ⇔ȱ¡ȱƽȱ¢ȱ
ǻŘǼȱ¢DZȱǻ¡ǰȱ¢Ǽȱƽȱǻ¢ǰȱ¡Ǽȱûȱȱ¡ǰȱ¢∈ȱȱ
ǻřǼȱDZȱǻ¡ǰȱ¢Ǽȱ≤ȱǻ¡ǰȱ£ǼȱƸȱǻ£ǰȱ¢Ǽȱûȱȱ¡ǰȱ¢ǰȱ£ȱ∈ȱȱ
ȱ
ȱ ȱ ȱ ȱ ȱ Ȭ£ǯȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ
ǰȱ ȱ ȱ £ ȱ ãȱ ȱ §ȱ ȱ ȱ ûǰȱ
ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ǯȱ DZȱ ȱ Ȭ
Ȭ£ȱ£ ȱȱãȱȱȱȱȱ£ ǰȱ ȱȱȱȱ
£ ȱȱǻŘȱȱŚǼȱȱûǯȱȱȱȱ ȱ£ȱ£ǰȱȱȱ
Ȭ£ȱȱȱȱûǯȱ
ȱ
ȱ ȱ ȱ ȱ ȱ Ȭ£ǰȱ ȱ Ȭ£ȱ ȱ ȱ ȱ ǻȱ
ȱ ȱ ȱ ȱ ȱ ǻǯȱ ŗşřśǼǰȱ ȱ ȱ Ȭ
ȱŗşŜśȱȱǼǯȱ ȱ£ȱȱȱãȱȱȱȱȱȬ
ȱ ǯȱ ȱ ȱ ȱ ãȱ ȱ ȱ ȱ ȱ Ȭ
ȱ DZȱãȱȱûȱȱǰȱ£ȱȱȱ
ȱȱǯȱȱȬ£ȱ£ ȱãȱŗȱȱŘȱȱȱȱȱ
ȱ £ȱ ȱ ǰȱ ȱ ŗȱ ȱ Řȱ £ȱ ûûǯȱ ȱ DZȱ
ǻǰȱǼȱƽȱřǰȱ ȱȱȱȱǮȃȱȱȱȱ£ȱǮȃȱȬ
ȱDZȱȱ →ȱȱ →ȱȱ →ȱȱǻûȱȱŗǰȱ£ȱȱřȱȱŚǼǯȱ
ȱȬ£ȱûȱȱȱȱǯȱȱ ȱȱȱ¡ȱǯǯȱ
ȱȱȱ DZȱûǰȱȬ¢ǰȱȬ
ǰȱǰȱ ǰȱȱȱȱǯȱ
ȱ
ȱȱȱ ȱ ȱȱȬ£ȱ£ ȱ£ ȱȱãȱ
ǯȱȱãȱȱȱȱȱȱȱȱ£ȱȱȱ¡ȱŗŖŖȱ
ȱǯȱȱ
ȱ
DZȱ ȱǯȱȱȱȱǰȱȱȱǯȱȱ
DZȱ ȱȱȱǯȱȱȱȱȬ£ȱûȱȱȱȱǯȱ
ǯȱDZȱ
ȱ
edit.in
anne marie
klipp klar
mathematik informatik
probleme loesungen
baerchen zwerglein
edit.out
d(anne, marie) = 3
anne I(1) --> manne T(3) --> marne T(4) -->
marie
========================
d(klipp, klar) = 3
8 Dynamische Programmierung
boese gute
299
klipp D(3) --> klpp T(3) --> klap T(4) -->
klar
========================
d(mathematik, informatik) = 5
mathematik T(1) --> iathematik T(2) --> inthematik T(3) --> infhematik T(4) --> infoematik
T(5) --> informatik
========================
d(probleme, loesungen) = 8
probleme T(1) --> lrobleme T(2) --> loobleme
T(3) --> loebleme T(4) --> loesleme T(5) -->
loesueme T(6) --> loesunme T(7) --> loesunge
I(9) --> loesungen
========================
d(baerchen, zwerglein) = 5
baerchen T(1) --> zaerchen T(2) --> zwerchen
T(5) --> zwerghen T(6) --> zwerglen I(8) -->
zwerglein
========================
d(boese, gute) = 4
boese D(1) --> oese T(1) --> gese T(2) --> guse T(3) --> gute
========================
ȱ
Problemanalyse und Entwurf der Lösung
ȱȱȱǰȱȱȱãȱ¡ȱƽȱ¡ŗ¡Řdz¡ȱȱ¢ȱƽȱ¢ŗ¢Řdz¢ȱȱȱ§ȱȱ
ȱȱȱǯȱȱȱȱȱȱȱȱ£ ȱȱ
£ȱ ȱ ȱ ǰȱ §ȱ ȱ Ȭ£ȱ £ ȱ ȱ ¡ȱ ǻǰȱ
Ǽǯȱȱ£ȱȱǰȱ ȱȱȱȱǯȱȱããȬ
ȱȱǰȱȱ¢ȱǽǾǽǾȱȱƸŗȱȱȱƸŗȱȱ£ǰȱȱ
ȱ Ȭ£ȱ £ ȱ ¡ŗ¡Řdz¡ȱ ǻŖȱ ≤ȱ ȱ ≤ȱ Ǽȱ ȱ ¢ŗ¢Řdz¢ȱ ǻŖȱ ≤ȱ ȱ ≤ȱ Ǽȱ §ȱ
ǻȱ£ȱȱȱǼǯȱȱȱ ȱȱȱȱŖȱȱȱȬ
ȱ Ŗǰȱ ŗǰȱ Řǰȱ dzǰȱ ȱ ûȱ ǻȱ ȱ ȱ ȱ ¡ŗ¡Řdz¡ȱ £ȱ ȱ ȱ
ȱȱȱǰȱ ȱȱûȱȱȱãǼǯȱȱȱŖȱ ȱ
ȱȱȱŖǰȱŗǰȱŘǰȱdzǰȱȱûȱǻȱȱȱȱȱȱȱ¢ŗ¢Řdz¢ȱ£ȱûȬ
ûǰȱ ȱ ȱ ȱ ãǰȱ ȱ ȱ ȱ ûȱ ȱ £Ǽǯȱ ȱ ȱ
£ȱǽǾǽǾȱ£ ȱȱãȱ¡ŗ¡Řdz¡ȱǻŗȱ ≤ȱǼȱȱ¢ŗ¢Řdz¢ȱǻŗȱ ≤ȱǼȱ£ȱǰȱ
ȱȱȱãDZȱ
ȱ
• ȱ ǽȬŗǾǽȬŗǾDZȱ ȱ ȱ ¡ȱ ƽȱ ¢ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱãȱǽǾǽǾȱƽȱǽȬŗǾǽȬŗǾȱDzȱ ȱ¡ȱ ≠ȱ¢ǰȱ ȱ¡ȱȱ¢ȱ £ǰȱ
ȱȱãȱǽǾǽǾȱƽȱǽȬŗǾǽȬŗǾƸŗȱǯȱ
• ȱǽȬŗǾǽǾDZȱ¢ŗ¢Řdz¢Ȭŗȱ ȱȱǽȬŗǾǽǾȱȱȱ¡ŗ¡Řdz¡ȱȱȬ
ǯȱǯǯȱ¢ŗ¢Řdz¢ȱȱȱ¡ŗ¡Řdz¡ȱȱǽȬŗǾǽǾƸŗȱǰȱ ȱȱ
£ȱȱȱ £ûȱȱȱ¢ȱǯȱȱ
300
Grundlegende Algorithmen mit Java
•
ȱ ǽǾǽȬŗǾDZȱȱȱ£ȱȱǰȱȱ ¢ŗ¢Řdz¢ȱȱ¡ŗ¡Řdz¡ȬŗȱȬ
£ǰȱȱǽǾǽȬŗǾǯȱǯǯȱȱ¢ŗ¢Řdz¢ȱȱ¡ŗ¡Řdz¡ȱȱǽǾǽȬŗǾƸŗȱȬ
ȱǰȱ ȱȱ£ȱȱȱãȱȱȱ¡ȱǯȱ
ȱ
ȱ£ȱǻǰȱǼȱƽȱŖǰȱ ȱ¡ȱƽȱ¢ǰȱȱ ȱǻǰȱǼȱƽȱŗǰȱ ȱ¡ȱ≠ȱ¢ǯȱȱđȱȱȱ
­ j , wenn i = 0 , j = 1, ..., m
°
T [i ][ j ] = ®i, wenn j = 0, i = 1, ..., n
°min (T [i-1][ j-1] + b (i, j ) , T [i-1][ j ] + 1, T [i ][ j-1] + 1) , wenn i = 1, ..., n, j = 1, ..., m
¯
ȱ
ȱȬ£ȱ£ ȱ ¡ŗ¡Řdz¡ȱȱ¢ŗ¢Řdz¢ȱȱȱǽǾǽǾǯȱûȱȱȱȬ
ȱȱȱȱ¢ȱǽǾǽǾȱȱDZȱ
ȱ
ȱ
ȏȱ ȱ ȱ ȱ ȱ
ȱ ȏȱ ȱ ȱ ȱ ȱ ȱ
ȏȱȱȱ Ŗȱ ŗȱ Řȱ řȱ Śȱ
ȏȱ Ŗȱ ŗȱ Řȱ řȱ Śȱ śȱ
ȱ ŗȱ ŗȱ Řȱ řȱ Śȱ
ȱ ŗȱ Ŗȱ ŗȱ Řȱ řȱ Śȱ
ȱ Řȱ ŗȱ Řȱ řȱ Śȱ
ȱ Řȱ ŗȱ Ŗȱ ŗȱ Řȱ řȱ
ȱ řȱ Řȱ Řȱ řȱ Śȱ
ȱ řȱ Řȱ ŗȱ ŗȱ Řȱ řȱ
ȱ Śȱ řȱ řȱ řȱ Śȱ
ȱ Śȱ řȱ Řȱ Řȱ Řȱ řȱ
ȱ śȱ Śȱ Śȱ Śȱ řȱ
ȱ
Ȭ£Ȭȱ
ȱ
ȱ ȱ ǻǼȱ ȱ ȱ ¢ȱ ǽǾǽǾȱ ǯȱ ȱ ȱ ǽǾǽǾȱ ȱ
ȱ ûȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǯȱ
ȱ ȱ ȱ ȱ £ȱ ǰȱ ȱ ȱ ȱ ǽǾǽǾȱ ȱ Ȭ
ȱ ȱ û §ȱ ȱ ǽŖǾǽŖǾǯȱ ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ
ȱ£ȱ ǽǾǽǾȱûȱǰȱȱȱȱûȱǯȱ ǽǾǽǾȱȱȱ ȱ
ȱ ȱ £DZȱ ȱ ȱ ǰȱ ûȱ ȱ ȱ ǯȱ ȱ
ȱȱȱ£ȱȱãȱȱǮȃȱȱȱȱȱǯȱ
ȱ ȱ ãȱ ȱ ȱ £ûȱ ȱ ǰȱ ȱ ȱ £ȱ ȱ
ȱȱȱȱȱǯȱ
ȱȱȱ ǻǼȱȱȱǯȱȱ ȱȱȱ ȱȬ
ȱȱȱȱãȱȱȱȱǽǾǽǾǯȱȱ£ȱȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ãȱ
ȱȱȱǰȱ ȱ ȱȱȱǯȱȱ
ȱ
8 Dynamische Programmierung
301
ȱ £ȱ ȱ ¡ȱ ƽȱ ¢ȱ ȱ ǽȬŗǾǽȬŗǾȱ ƽȱ ǽǾǽǾȱ ǰȱ ȱ ȱ ǽǾǽǾȱ ȱ ǽȬ
ŗǾǽȬŗǾȱȱȱȱȱȱ ȱ£ȱȱȱȱȱȱǻ ȱ
ȱûȱǽǾǽǾȱȱ§ȱǷǼȱȱȱ ǻǼȱȱȱ
ȱDZȱ
ȱ
flag = true;
writeSolution(out, m - 1, n - 1, new StringBuilder(yaux));
ȱ
ȱ¡ȱ ≠ȱ¢ȱȱǽȬŗǾǽȬŗǾƸŗȱƽȱǽǾǽǾȱǰȱȱȱǽǾǽǾȱȱǽȬŗǾǽȬŗǾȱȱȱ
ȱ £ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǻ ȱ ȱ ûȱ ǽǾǽǾȱ ȱ
§ȱ ǷǼǯȱ ȱ ûȱ ȱ ûȱ ûȱ ȱ ȱ ȱ ¢Ȭ
¡ȱ ǰȱ ȱ ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱ£ȱȱȱȱȱȱDZȱ
ȱ
flag = true;
yaux.replace(n-1, n, x.substring(m-1, m));
writeSolution(out, m - 1, n - 1,
new StringBuilder(yaux));
out.printf("%s T(%d) --> ", yaux, n);
ȱ
ȱ ȱ ȱ ȱ ǰȱ ȱ ǽǾǽȬŗǾȱ ȱ §ȱ ȱ
ǽǾǽǾȱ ȱ ǻǽǾǽǾȱ ƽȱ ǽǾǽȬŗǾƸŗǼȱ ȱ ǽȬŗǾǽǾȱ ȱ §ȱ ȱ ǽǾǽǾȱ ȱ
ǻǽǾǽǾȱ ƽȱ ǽȬŗǾǽǾƸŗǼDZȱ ûȱ ûǰȱ ǻǼȱ ȱ ȱ Ȭ
ȱ ǰȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ǰȱ ȱ ȱ
ȱȱȱȱȱȱȱ ¡ȱŖȱǰȱȱ ȱȱ
ȱ £ǯȱ ǯȱ ǻǻ¡ǯǻȬŗǼƽƽ¢ǯǻȬŗǼdzǼȱ ȱ ¡ǯǻǼƽƽ¢ǯǻǼǯȱ Ȭ
ȱȱȱȱȱȱǻǰȱǰȱǰȱǼǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P13EditDistance {
private static final String FileInputName = "edit.in";
private static final String FileOutputName = "edit.out";
private int T[][];
private StringBuilder x, y;
P13EditDistance(StringBuilder x, StringBuilder y) {
this.x = x;
this.y = y;
302
Grundlegende Algorithmen mit Java
this.T = new int[y.length() + 1][x.length() + 1];
}
private int getEditDistance() {
int m = x.length();
int n = y.length();
if (m == 0)
return n;
if (n == 0)
return m;
for (int i = 0; i <= m; i++)
T[0][i] = i;
for (int i = 0; i <= n; i++)
T[i][0] = i;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (x.charAt(j - 1) == y.charAt(i - 1)) {
T[i][j] = T[i - 1][j - 1];
} else {
T[i][j] = T[i - 1][j - 1] + 1;
}
if (T[i][j] > T[i - 1][j] + 1)
T[i][j] = T[i - 1][j] + 1;
if (T[i][j] > T[i][j - 1] + 1)
T[i][j] = T[i][j - 1] + 1;
}
return T[n][m];
}
private void writeSolution(PrintStream out,
int m, int n, StringBuilder yaux) {
boolean flag = false;
if (m != 0 || n != 0) {
if (m > 0 && n > 0) {
if (x.charAt(m - 1) == y.charAt(n - 1)) {
if (T[n - 1][m - 1] == T[n][m]) {
flag = true;
writeSolution(out, m - 1, n - 1, yaux);
}
} else {
if (T[n - 1][m - 1] + 1 == T[n][m]) {
flag = true;
yaux.replace(n-1, n, x.substring(m-1, m));
writeSolution(out, m - 1, n - 1,
new StringBuilder(yaux));
out.printf("%s T(%d) --> ", yaux, n);
}
}
8 Dynamische Programmierung
303
}
if (n > 0 && !flag) {
if (T[n][m] == T[n - 1][m] + 1) {
flag = true;
yaux.delete(n-1, n);
writeSolution(out, m, n - 1,
new StringBuilder(yaux));
out.printf("%s I(%d) --> ", yaux, n);
}
}
if (m > 0 && !flag) {
if (T[n][m] == T[n][m - 1] + 1) {
yaux.insert(n, x.charAt(m-1));
writeSolution(out, m - 1, n,
new StringBuilder(yaux));
out.printf("%s D(%d) --> ", yaux, n + 1);
}
}
}
}
void writeSolution(PrintStream out) {
out.printf("d(%s, %s) = %d%n",
this.x, this.y, this.getEditDistance());
writeSolution(out, x.length(), y.length(),
new StringBuilder(this.y));
out.println(this.y);
out.println("========================");
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
out = new PrintStream(new File(FileOutputName));
while (scanner.hasNext()) {
StringBuilder x = new StringBuilder(scanner.next());
if (!scanner.hasNext())
break;
StringBuilder y = new StringBuilder(scanner.next());
new P13EditDistance(x, y).writeSolution(out);
}
} finally {
if (scanner != null) {
scanner.close();
304
Grundlegende Algorithmen mit Java
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǯǯȱ ȱ ȱ Ȭ Ȭȱ ǯȱ £ȱ ȱ ȱ
ȱ ǯǯȱ ûȱ ȱ ȱ ȱ ¢ȱ Ȭ
ȱ ȱ ȱ ȱ ǯǯǰȱ ȱ ȱ ȱ ȱ ¢ȱ
ȱ¢ȱǽǾȱ ȱǻȱ ȱȱȱ¢ǻǼǼǯȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ DZȱ ûȱ ȱ £ȱ ǰȱ ûȱ
ȱãȱǰȱûȱȱûȱǯȱȱ ȱȱȱȱǻǰȱȱȱȱǼȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ Ȭ
ȱǰȱȱȱ ȱȱ ǯȱDZȱ
ȱ
ȱ
řǯ
edit1.in
edit1.out
probleme loesungen 4 2 1
baerchen zwerglein 5 3 1
boese gute 2 3 1
d(probleme, loesungen) = 17
probleme D(1) --> robleme D(1) -->
obleme D(1) --> bleme D(1) --> leme
I(2) --> loeme D(4) --> loee I(4) -->
loese I(5) --> loesue I(6) --> loesune
I(7) --> loesunge I(9) --> loesungen
========================
d(baerchen, zwerglein) = 19
baerchen D(1) --> aerchen D(1) --> erchen I(1) --> zerchen I(2) --> zwerchen D(5) --> zwerhen D(5) --> zweren
I(5) --> zwergen I(6) --> zwerglen
I(8) --> zwerglein
========================
d(boese, gute) = 7
boese D(1) --> oese T(1) --> gese T(2)
--> guse T(3) --> gute
========================
ȱ ȱ ȱ λȱ ȱ ȱ ǯȱ ȱ ãȱ ȱ ȱ ȬȬ
ȬȱȱȱȱȱDZȱ
ǻλǰλǼȱƽȱŖȱ
ǻ¡ŗ¡Řdz¡ǰȱλǼȱƽȱȱȱûȱȱȱ≥ŗȱ
ǻλǰȱ¢ŗ¢Řdz¢Ǽȱƽȱȱȱûȱȱȱ≥ŗȱ
ȱ
8 Dynamische Programmierung
305
­
°max{m, n}, wenn es keine gemeinsamen Buchstaben gibt
°
d ( x1 x2 ...xm , y1 y 2 ... y n ) = ®min ( d ( x1 ..xi −1 , y1 .. y j −1 ) + d ( xi +1 ..xm , y j +1 .. y n )),
ȱ
° xi = y j
°¯
wenn es mindestens einen gemeinsamen Buchstaben gibt
Śǯ
ȱ
ȱȱȱȱûǯȱȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ǯȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ Ȭȱ ȱ Ȭ
ȱȱȱȱȱȱȱ ȱǯȱȱȱȱ
ǰȱȱȱȱȱ ǰȱ£ǯȱǯȱDZȱȱ Ȭ
ǰȱȱûȱ¡ȱǻǻǼǰȱǻǼǰȱǻǼǼǰȱ§Ȭ
ȱȱȱǻǻǼǼǰȱȱȱȱǻǻǼǰȱȬ
ǻǼǰȱ ǻǼǰȱ ǻǼǰȱ ǻǼǼǰȱ ȱ ȱ Ȭ
ȱ ǻ¡ǻǼǰȱ ¡ǻǼǼǰȱ £ȱ ȱ ȱ ǻ ǻǼǰȱ
ǻǼǰȱǻǼǼǰȱ ȱǻǻǼǼǯȱ
Problem 14. Arbitrage
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ǰȱ ȱ
ȱȱȱȱ§ȱ ȱ£ȱ£ǯȱȱȬ
ȱ ȱ ȱ ȱ §ǯȱ ȱ ȱ £ȱ ȱ ȱ ȱ Ȭȱ Ŗǰśŗȱ
ȱȱȱãǰȱȱȱȱȱŗǰŚŞȱȱȱȱȱ
ȱ ŗǰřŜȱ Ȭǰȱ ȱ ȱ ȱ ȱ ȱ ŗǰŖŘŜśŘŞȱ ȱ ȱ ȱ ŘǰŜȱ £ȱ
ǯȱȱ
ȱ
ŗǞȱȘȱŖǰśŗǡȦǞȱȘȱŗǰŚŞǧȦǡȱȘȱŗǰřŜǧȦǞȱƽȱŗǰŖŘŜśŘŞǞȱ
ȱ
ȱȱȱȱ¡ȱûȱ£ȱǰȱȱ ȱȱđȱǯȱ
ȱȱȱǰȱȱǰȱȱȱȱȱȱȱ
ȱ Ȭȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ǰȱ ȱ ǯȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ §ȱ
ȱȱȱǻȱ ǰȱȱȱǼǯȱȱDZȱ ȱȱȱȬ
ǯȱ ãȱ ȱ ȱ §ȱ ǯȱ ȱ ȱ ȱ ȱ Ȭ
ȱ Ȭȱ ǰȱ ȱ ȱ £ȱ ȱ §ȱ ǰȱ ȱ ȱ ȱ
ȱǰȱȱȱȱŘ≤≤ŘŖǯȱȱȱȱȱȱȱȱ ȱȱ§Ȭ
ȱ£ǰȱȱȱȱȱȱȱȱǯȱȱȱȱȱȱ
ȱȱȱȱȱȱ§ȱŗȱ £ȱȱȱ Ȭŗȱ§Ȭ
ȱ ǻ£ȱ §ȱ Řǰȱ řǰȱ dzǰȱ Ǽǰȱ ȱ £ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ§ȱŘȱ£ȱȱȱ§ȱǻ£ȱ§ȱŗǰȱřǰȱŚǰȱdzǰȱǼȱ ǯȱDZȱ
306
Grundlegende Algorithmen mit Java
ȱ ȱ ûȱ ȱ ȱ ûǰȱ ȱ ȱ ȱ ȱ ȱ
ǰȱ ȱ ȱ ȱ £ȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ
§ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ £ǯȱ ȱ
ȱŘȱȬǁȱŗȱȬǁȱŘȱ£ȱȱ§ȱ£ ȱȱǻȱ§ȱŘȱȱ
ȱ§ȱŗȱǰȱȱȱ ȱ§ȱŘǼǯȱ ȱȱȱ ǯȱ
ȱȱȱȱ£ȱǻȱŗDZǼǰȱȱȱȱȱȬȱȱ §Ȭ
ȱ ȱ ǻȱ ŘǼǰȱ ȱ ȱ ȱ ȱ đȱ ȱ ȱ ȱ Ȭ
£ǯȱȱȱ ȱȱȱȱȱȱȱ ȱǰȱȱȱȱ
ȱȱ§ȱ ǯȱȱȱȱȱǰȱ ȱȱȱȱȱ Ȭ
ȱǮȱȱȱǷȃȱǯȱ
arbitrage.in
3
1.2 .89
.88 5.1
1.1 0.15
4
3.1 0.0023 0.35
0.21 0.00353 8.13
200 180.559 10.339
2.11 0.089 0.06111
2
2.0
0.45
arbitrage.out
Fall 1:
Waehrung 2
2 -> 1 -> 2
1.056
Fall 2:
Waehrung 3
3 -> 1 -> 2 -> 3
2.189
Fall 3:
Es gibt keine Loesung!
ǻǰȱ ȱȱǰȱŘŖŖŖǰȱ£Ǽȱ
ȱ
Problemanalyse und Entwurf der Lösung
ȱ£ ȱ¢ȱǽǾǽǾȱȱȱȱȱȱȱȱ
ȱǰȱȱȱȱǮȃȱ ȱ ǯȱȱȱȱȬ
ȱ ǰȱ ȱ ȱ ûȱ ȱ ȱ ȱ §ȱ ȱ ȱ ȱ ȱ ȱ §ȱ ȱ
§ǯȱûȱȱȱ ȱȱûûǰȱȱûȱȱȱȱȱû£ǯȱ
ûȱ ȱ §ȱ ȱ ȱ ȱ ȱ ǽǾǽǾȱ ȱ ŗǯȱ ȱ ǽǾǽǾȱ ȱ
ȱȱ£ȱȬȱǯȱȱ
8 Dynamische Programmierung
307
ȱ
ȏ ȏ ǻǼȱ
ȱ
ȱȱ ȱ¡ȱǽǾǽǾȱȱȱ¢ȱȱ
ȱ
ȱȱȱǻƜŗǰȱDzȱȱŗǼȱ¡ȱ
ȱ
ȱȱȱȱȱǻƜŗǰȱDzȱȱŗǰȱƾǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱȱǻƜŗǰȱDzȱȱŗǰȱƾǼȱ¡ȱ
ȱ
ȱȱȱȱȱȱȱȱȱ ǻǽǾǽǾȘǽǾǽǾȱǁȱǽǾǽǾǼȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱƜǽǾǽǾȘǽǾǽǾȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱƜǽǾǽǾȱ
ȱ
ȱȱȱȱȱȱȱȱȱȏ ȱ
ȱ
ȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȏȱ
ȱ
ȱȱȏȱ
ȱ
ȱȱȱǽǾǽǾȱ
ȱ
ȏ ȏȱ ȏ ǻǼȱ
ȱ
ȱ
ȱȱȱȱ
− ȱ ǻǼDZȱ ȱ ȱ Ȭǰȱ ȱ ȱ ȱ ȱ ȱ ǻǼȱ
ȱȱ£ȱȱ§ȱȱ ȱȱȱ£ǰȱȱȱȬȱȱ
§ǯȱȱ ȱȱȱȱȱȱ ≥ȱŗǯŖŗȱǰȱȱȱȱ
ȱûȱãǰȱȱ ȱǯȱȱȱȱȱǰȱȱ
ȱãȱûDzȱ
− ȱ ǻǼDZȱ ȱ ǰȱ ȱ ȱ ȱ ȱ §ȱ ǯȱ ȱ
ȱ ȱ ȱ ¡ȱ ǽǾǽǾǰȱ ȱ ȱ ȱ £ûȱ £ȱ ǯȱ ȱ
£ȱ ȱ ȱ ȱ ȱ £ ȱ ȱ §ȱ ǽǾǽǾȱ ȱ ȱ ȱ ȱ
ȱǽǾǽǾȱȱȬŗǯȱȱȱǽǾǽǾȱȱȱȱ§ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ¡ȱ ȱ £ ȱ ȱ ȱ ȱ ǻȱ £ȱ
¡ ǰȱ ȱȱȱ§ȱȱȱȱ§ȱȱ Ǽǯȱ
ȱ
Programm
import java.io.*;
import java.util.*;
public class P14StocksFluctuation {
private static final String FileInputName = "arbitrage.in";
private static final String FileOutputName = "arbitrage.out";
private static void recoverPath(PrintStream out,
int pred[][], int i, int j) {
int t = pred[i][j];
if (i != t) {
308
Grundlegende Algorithmen mit Java
recoverPath(out, pred, i, t);
out.print(" -> ");
out.print(t + 1);
}
}
static boolean find(PrintStream out, int n,
float table[][], int pred[][]) {
int i, j, k;
for (k = 0; k < n; k++)
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (table[i][k] * table[k][j] > table[i][j]) {
pred[i][j] = pred[k][j];
table[i][j] = table[i][k] * table[k][j];
if (i == j && table[i][j] >= 1.01) {
out.print(" Waehrung ");
out.println(i + 1);
out.print(' ');
out.print(i + 1);
recoverPath(out, pred, i, i);
out.print(" -> ");
out.println(i + 1);
out.printf(Locale.ENGLISH, " %.3f%n",
table[i][i]);
return true;
}
}
return false;
}
public static void main(String[] args) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(
new File(FileInputName)).useLocale(Locale.ENGLISH);
out = new PrintStream(new File(FileOutputName));
int numCase = 0;
while (scanner.hasNextInt()) {
int n = scanner.nextInt();
float table[][] = new float[n][n];
int pred[][] = new int[n][n];
for (int i = 0; i < n; i++) {
table[i][i] = 1.0f;
for (int j = 0; j < n; j++)
if (i != j) {
table[i][j] = scanner.nextFloat();
8 Dynamische Programmierung
309
pred[i][j] = i;
}
pred[i][i] = -1;
}
out.printf("Fall %d: %n", ++numCase);
if (!find(out, n, table, pred))
out.println(" Es gibt keine Loesung!");
}
} finally {
if (scanner != null) {
scanner.close();
}
if (out != null) {
out.close();
}
}
}
}
ȱ
Aufgaben
ŗǯ
Řǯ
řǯ
£ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ
§ȱȱȱ ȱȱȱȱ£ȱǯȱ
ȱ ȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãđȱ
ȱȱ ǯȱ
ȱȱȱȱȱȱǻȱȱȱ£ǯȱǯȱȱ ȱȬ
Ǽȱȱȱȱǰȱȱȱȱ ûȱȱ ȱȱȱ
ȱǯȱȱȱȱȱȱȱ ȱȱȱ
ȱȱȱûȱȱȱȱȱȱȬǯȱ
ȱ
ãȱȱ¢ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱȱǰȱȱ
ȱ
ȱ
ȱ
9
Potenzsummen
ȱ
ȱ
Problembeschreibung
ȱȱȱûȱȱȱ≥ȱŖȱǯȱȱ£ȱûȱȱDZȱ
ȱ
S k (n) = 1k + 2 k + 3k + ... + n k ǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ǻŗǼȱ
ȱ
ȱȱ ȱǻȱ§ȱ ȱȱȱǻŗřǼȱǼǰȱȱǻǼȱ
ȱ¢ȱǻƸŗǼȬȱ ȱȱȱǰȱȱȱȱ £ȱǰȱǯǯȱȱȱ
ǻǼȱȱDZȱ
ȱ
1
ȱ
ȱ
ȱ
ȱ
ǻŘǼȱ
S k ( n) =
(ak +1n k +1 + a k n k + ... + a1n + a0 ) ǯȱ
M
ȱ
ȱ ȱ Ƹŗǰȱ ǰȱ ǯǯǯǰȱ ŗǰȱ Ŗȱ ȱ £ȱ ǰȱ ȱ ȱ đȱ ǯȱ ȱ ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ǻǰȱ Ƹŗǰȱ ǰȱ ǯǯǯǰȱ ŗǰȱ ŖǼȱ ûȱ ȱ ȱ ȱ ǰȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱûȱȱȱûȱȱǯȱ
DZȱȱȱǯȱȱȱȱȱûȱȱǻŖȱ≤ȱȱȱ≤ȱŘŖǼǯȱ
DZȱȱǯȱȱûȱȱȱȱȱȱȱȱǰȱƸŗǰȱǰȱǯǯǯǰȱŗǰȱŖȱ
ȱ ǰȱ ȱȱȱȱȱǯȱDZȱ
ȱ
psum.in
2
5
0
16
psum.out
6 2 3 1 0
12 2 6 5 0 –1 0 0
1 1 0
510 30 255 680 0 -2380 0 8840 0 -24310 0 44200 0 -46988 0
23800 0 -3617 0
ȱȱȱȱȱȱȱǻȱȬȱȱȱȱǰȱŗşşŝȬşŞǼȱȱ
Problemanalyse. Algebraische Modellierung.
ȱȱǻǼȱDZȱ
S 0 (n) =
n
¦i = n
0
i =1
ǻřǼȱ
312
Grundlegende Algorithmen mit Java
n
S1 (n)
¦i =
i =1
n(n + 1) 1 2
= ( n + n) ȱ
2
2
n
¦i =
S2 (n) =
2
i =1
n
S 3 ( n) =
3
i =1
n
S 4 ( n) =
ȱ
ȱ
ȱ
ȱ
ǻŚǼȱ
n(n + 1)(2n + 1) 1
= ( 2n3 + 3n 2 + n) ȱȱ
6
6
ȱ
ȱ
ȱ
ȱ
ǻśǼȱ
n 2 (n + 1) 2 1 4
= ( n + 2n 3 + n 2 ) ȱ
4
4
ȱ
ȱ
ȱ
ȱ
ǻŜǼȱ
n(n + 1)(2n + 1)(3n 2 + 3n − 1) 1
= (6n5 + 15n 4 + 10n3 − n) ȱȱȱȱȱȱ ȱȱȱ
30
30
ȱ
ǻŝǼȱ
¦i =
¦
i4 =
i =1
ȱ
ȱ
ȱ ȱ ȱ ȱ §ǯȱ ȱ ãȱ ȱ ȱ §ȱ ȱ
ȱ ǯȱȱ ȱ£ȱśǻǼȱǯȱȱ ȱȱ ȂȱȬ
ȱȱ DZȱ
§ 6·
§6·
§6·
§6·
§ 6·
(i − 1) 6 = i 6 − ¨¨ ¸¸i 5 + ¨¨ ¸¸i 4 − ¨¨ ¸¸i 3 + ¨¨ ¸¸i 2 − ¨¨ ¸¸i + 1
©1 ¹
© 2¹
©3¹
© 4¹
©5¹
(8)
ȱ
ȱȱ§ȱ£DZȱ
ȱ
i 6 − (i − 1) 6 = 6i 5 − 15i 4 + 20i 3 − 15i 2 + 6i − 1
(9)
ȱȱȱŗȱȱȱ§ȱDZȱ
ȱ
n
n
n
n
n
n
n
i =1
i =1
¦ (i − (i − 1) ) = 6¦ i − 15¦ i + 20¦ i − 15¦ i + 6¦ i − ¦1 ,
6
i =1
6
5
i =1
4
i =1
3
i =1
2
k =1
(10)
ȱ£ȱȱȱȱȱȱDZȱ
n 6 = 6 S 5 (n) − 15S 4 (n) + 20S 3 (n) − 15S 2 (n) + 6S1 (n) − S 0 (n)
(11)
ȱ ȱǻŗŗǼȱ ȱãȱ£DZȱ
ȱ
S 5 (n) =
n 2 (n + 1) 2 (2n 2 + 2n − 1) 1
= ( 2n 6 + 6n 5 + 5n 4 − n 2 )
12
12
ȱȱȱȱȱûȱ£DZȱ
ȱ
(12)
9
Potenzsummen
313
(k + 1) S k (n) =
§ k + 1·
§ k + 1·
§ k + 1·
§ k + 1·
¸¸S k −1 (n) − ¨¨
¸¸ S k −2 (n) + ... + (−1) p ¨¨
¸¸ S k − p+1 (n) + ... + (−1) k ¨¨
¸¸ S1 (n) + (−1) k +1 S 0 (n)
n k +1 + ¨¨
2
3
p
©
¹
©
¹
©
¹
© k ¹
(13)
Von der Rekursionsgleichung zum Algorithmus
ȱ ǻŗřǼȱ ǰȱ ȱ ȱ £ȱ ȱ ȱ ȱ ǻǰȱ Ƹŗǰȱ ǰȱ ǯǯǯǰȱ ŗǰȱ ŖǼȱ ûȱ ȱ ȱ
ȱ ȱ ȱ £ȱ ãǰȱ ȱ ȱ ȱ £ȱ ȱ ǰȱ
§ȱ Ŗǰȱ ŗǰȱ ǯǯǯǰȱ Ȭŗǰȱ ǯȱ ȱ ȱ ȱ ȱ ȱ
ȱ ȱ ǰȱ ȱ £ȱ ȱ §ȱ ȱ ȱ £ȱ £ȱ
ãǯȱȱ ȱȱ¢ȱǽǾȱ£ǰȱȱȱȱǽŖǾǰȱǽŗǾǰȱǽŘǾǰdzǰȱǽǾȱ
ȱ ȱ ȱ DZȱ ǽǾȱ ȱ ȱ ûȱ ȱ ȱ ȱ ȱ
ȱûȱǻǼǰȱŖȱ≤ȱȱ≤ȱǯȱ
ȱ
ȱ£ ȱ¢ȱǽǾǽǾȱȱ ȱȱȱȱǻƸŗǰȱǰȱǯǯǯǰȱŗǰȱ
ŖǼȱûȱŖȱ ≤ȱȱ ≤ȱȱȱȱǰȱȱȱȱȱȱȱ £ȱ
ûȱǻǼȱǯȱ
ȱ
ȱȱȱ¡ȱǽǾǽǾȱȱȱȱǽǾȱ
ǽŖǾǽŖǾȱ
ǽŖǾǽŗǾȱ
ȱ
ȱ
ȱ
ȱ
ǽŖǾȱ
ǽŗǾǽŖǾȱ
ǽŗǾǽŗǾȱ
ǽŗǾǽŘǾȱ ȱ
ȱ
ȱ
ǽŗǾȱ
ǽŘǾǽŖǾȱ
ǽŘǾǽŗǾȱ
ǽŘǾǽŘǾȱ ȱ
ȱ
ȱ
ǽŘǾȱ
ǯǯǯȱ
ǯǯǯȱ
ȱ
ǯǯǯȱ ȱ
ȱ
ǯǯǯȱ
ǽȬŗǾǽŖǾȱ ǽȬŗǾǽŗǾȱ ǽŗǾǽŘǾȱ ǯǯǯȱ ǽȬŗǾǽǾȱ ȱ
ǽȬŗǾȱ
ǽǾǽŖǾȱ
ǽǾǽŗǾȱ
ǽǾǽŘǾȱ ǯǯǯȱ ǽǾǽǾȱ
ǽǾǽƸŗǾȱ ǽǾȱ
ȱ
ȱȱȱȱȱǻŘǼȱDZȱ
ȱ
S k (n) =
(
)
1
A[k ][k + 1]n k +1 + A[k ][k ]n k + ... + A[k ][1]n + A[k ][0] ȱ
M [k ]
ȱ
ȱ
ǻŗŚǼȱ
ȱ
ȱ ȱ ȱ ȱ ȱ ûȱ ȱ ȱ ǻǽǾǰȱ ǽǾǽƸŗǾǰȱ ǽǾǽǾǰȱ dzǰȱ
ǽǾǽŗǾǰȱ ǽǾǽŖǾǼȱ ȱ ȱ ȱ ȱ ȱ ȱ ǻǽǾǰȱ ǽǾǽƸŗǾǰȱ ǽǾǽǾǰȱ dzǰȱ
ǽǾǽŗǾǰȱǽǾǽŖǾǼȱûȱŖȱ ≤ȱȱǀȱȱǯȱȱȱȱȱȱȱ ȱǰȱ
ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱ§ǯȱȱȱ£DZȱ
314
Grundlegende Algorithmen mit Java
( k + 1) S k (n) = n k +1
§ k + 1·
1
k
k −1
+ ¨¨
¸¸( M [k − 1] ( A[k − 1][k ]n + A[k − 1][k − 1]n + ... + A[k − 1][1]n + A[k − 1][0]))
2
©
¹
§ k + 1·
1
¸¸(
(A[k − 2][k − 1]n k −1 + A[k − 2][k − 2]n k −2 + ... + A[k − 2][1]n + A[k − 2][0]))
− ¨¨
© 3 ¹ M [k − 2]
ǻŗśǼ
+ ... +
§ k + 1·
1
¸¸(
( −1) p ¨¨
( A[k + 1 − p ][k + 2 − p ]n k + 2− p + ... + A[k + 1 − p ][1]n + A[k + 1 − p ][0]))
© p ¹ M [k + 1 − p]
+ ..
§ k + 1· 1
¸¸(
( −1) k ¨¨
( A[1][2]n 2 + A[1][1]n + A[1][0])) +
© k ¹ M [1]
§ k + 1· 1
¸¸(
( −1) k +1 ¨¨
( A[0][1]n + A[0][0]))
© k + 1¹ M [0]
ȱ
ȱȱȱȱȱȱȱŖǰȱŗǰȱǯǯǯǰȱȱȱȱȱȱǻŗřǼȱȱ¢ȱ
ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ £ȱ ȱ ȱ ȱ ȱ ȱ
¢ȱȱ ȱǻƸŗǼDZȱ
ȱ
(k + 1) S k (n) = n k +1 +
§ k + 1· A[k − 1][k ]
¸¸
)+
n k (¨¨
© 2 ¹ M [k − 1]
§ k + 1· A[k − 1][k-1] § k + 1· A[k − 2][k − 1]
¸¸
¸¸
)+
n k −1 (¨¨
- ¨¨
© 2 ¹ M [k-1]
© 3 ¹ M [k − 2]
§ k + 1· A[k − 1][k − 2] § k + 1· A[k − 2][k − 2] § k + 1· A[k − 3][k − 2]
¸¸
¸¸
¸¸
− ¨¨
+ ¨¨
)+
n k −2 (¨¨
© 2 ¹ M [k − 1]
© 3 ¹ M [k − 2]
© 4 ¹ M [k − 3]
...
ǻŗŜǼ
§ k + 1 · A[ p − 1][ p]
§ k + 1· A[k − 1][ p] § k + 1· A[k − 2][ p]
¸¸
¸¸
¸¸
− ¨¨
+ ... + (−1) k + 2-p ¨¨
)...
n p (¨¨
2
3
−
−
[
1
]
[
2
]
M
k
M
k
©
¹
© k + 2 − p ¹ M [ p − 1]
©
¹
§ k + 1· A[k − 1][1] § k + 1· A[k − 2][1]
§ k + 1· A[0][1]
¸¸
¸¸
¸¸
− ¨¨
+ ... + (−1) k +1 ¨¨
)+
n(¨¨
2
3
−
−
[
1
]
[
2
]
M
k
M
k
©
¹
©
¹
© k + 1¹ M [0]
§ k + 1· A[k − 1][0] § k + 1· A[k − 2][0]
§ k + 1· A[0][0]
¸¸
¸¸
¸¸
− ¨¨
+ ... + (−1) k +1 ¨¨
(¨¨
)
3
2
−
−
[
1
]
[
2
]
M
k
M
k
©
¹
©
¹
© k + 1¹ M [0]
ȱȱȱǻŗŜǼȱãȱȱ £ǰȱȱȱȱȱȱ
ûȱǰȱ£ȱ ȱ£DZȱ
ȱ
9
Potenzsummen
§ k +1 ·
¨¨
¸¸
k +1-t © k + 1 − t ¹
W [t ] = ( −1)
, ûȱȱȱȱŖȱǂȱȱǂȱȬŗȱ
M [t ]
315
(17)
ȱǻŗŝǼȱ ȱȱǻŗŜǼȱ£DZȱ
ȱ
( k + 1) S k ( n) = n k +1 +
n k (W [k − 1] A[ k − 1][k ]) +
n k −1 (W [k − 1] A[ k − 1][k − 1] + W [ k − 2] A[ k − 2][k − 1]) +
n k − 2 (W [k − 1] A[ k − 1][k − 2] + W [k − 2] A[k − 2][k − 2] + W [k − 3] A[ k − 3][k − 2]) +
...
ǻŗŞǼ
n p (W [ k − 1] A[ k − 1][ p ] + W [k − 2] A[k − 2][ p ] + ... + W [ p − 1] A[ p − 1][ p]) +
...
n(W [k − 1] A[ k − 1][1] + W [k − 2] A[k − 2][1] + ... + W [0] A[0][1]) +
(W [k − 1] A[k − 1][0] + W [ k − 2] A[ k − 2][0] + ... + W [0] A[0][0])
ȱȱȱȱȱȱȱǯȱȱǽŖǾǽŖǾƽŖȱ§ȱȱȬ
ȱǽŖǾǽŖǾǽŖǾȱ ǯȱȱ £ȱȱ£ȱȱȱȱȱ ȱãȬ
ȱȱȱ¢ȱȱȱûȱǽǾȱȱ DZȱ
ȱ
­ k −1
° W [t ] A[t ][0] für p = 0
° t =1
°° k −1
(19)
F [ p ] = ® W [t ] A[t ][ p] für alle p mit 1 ≤ p ≤ k
°t = p −1
°1 für p = k + 1
°
°¯
¦
¦
ȱ ȱȱǻŗşǼȱȱǻŗŞǼȱ£ǰȱDZȱȱ
ȱ
S k ( n) =
ȱ
1
( F [ k + 1]n k +1 + F [ k ]n k + F [ k-1]n k-1 + ...F [1]n + F [0])
k +1
(20)
ȱȱȱǰȱȱȱȱȱȱȱ§ȱǯȱȱ
ûȱ ȱȱȱȱȱȱǯȱȱȱ ǰȱȱ ȱȱ
ȱȱȱȱǽŖǾǰȱǽŗǾǰȱdzǰȱǽǾǰȱǽƸŗǾȱȱȱȱȱȬ
ǯȱȱ ȱȱȱǻŘŖǼDZȱ
ȱ
316
Grundlegende Algorithmen mit Java
1
( F'[ k + 1]n k +1 + F'[k ]n k + F'[k-1]n k-1 + ...F'[1]n + F'[0]) ,
ȱ
ȱ
ȱǻŘŗǼȱ
( k + 1)Q
F'[r ] = F [r ] ⋅ Q, 0 ≤ r ≤ k + 1
ȱ
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ǽǾȱ ǰȱ ȱ
ȂǽǾȱ£ȱǰȱȱǻƸŗǼȱȱȱȱȱûȱǻǼȱǯȱ
S k (n) =
Der Algorithmus
ȱȱȱȱȱǰȱȱǽŖǾƽŗǰȱǽŖǾǽŗǾƽŗǰȱǽŖǾǽŖǾƽŖǯȱȱ
ȱȱȱDZȱ
ȱ
ȏȱ
ȱ
ŗǯ ȱȱǻŖȱ≤ȱȱ≤ȱŘŖǼȱ
ȱ
Řǯ ǻȱǽƸŗǾǽƸŗǾȱǼȱ
ȱ
řǯ ǽŖǾƽŗǰȱǽŖǾǽŗǾƽŗǰȱǽŖǾǽŖǾƽŖȱ
Śǯ ȱǻȱ←ȱŗǰȱDzȱȱŗǼȱ¡ȱȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱŚǯŗǯȱȱƽȱŗȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱŚǯŘǯȱȱǻȱ←ȱȬŗǰȱŖDzȱȱȬŗǼȱ¡ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱǽǾȱƽȱ¢ǻȱȘȱǽƸŗǾǽƸŗȬǾȦǽǾǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱƽȱȱȘȱǻȬŗǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱŚǯřǯȱȱǻȱ←ȱǰȱŖDzȱȱȬŗǼȱ¡ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱǽǾȱƽȱǻŖȦŗǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱǻȱ←ȱȬŗǰȱȬŗDzȱ≥ȱŖDzȱȱȬŗǼȱ¡ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǯȱǻǽǾȘǽǾǽǾǼȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱŚǯŚǯȱǽƸŗǾȱƽȱȱǻŗȦŗǼȱ
ȱ
ȱȱȱŚǯśǯȱȱȱȱȱȱȱȱȱȱƽȱȱǻǽǾǰȱƸŗǼȱ
ȱ
ȱȱȱŚǯŜǯȱǽǾȱȱȱƽȱǻƸŗǼȘȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱŚǯŝǯȱȱǻȱ←ȱƸŗǰȱŖDzȱȱȬŗǼȱ¡ȱȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ¡ȱȱȱƽȱ¢ȱǻǽǾȘǼȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱǽǾǽǾȱƽȱǻ¡Ǽȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
ȱ
ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȏȱ
śǯȱȱȱȱȱȱȱȱǽǾǰȱǽǾǽƸŗǾǰȱǽǾǽǾǰȱdzǰȱǽǾǽŗǾǰȱǽǾǽŖǾȱ
ȱ
ȱȏ ȏ
ȱ
ȱ
9
Potenzsummen
•
317
ȱȱŘȱȱȱȱ£ȱȱ£ȱȱƸŗȱǻ§đȱ
ȱ ǻŗřǼȱ ȱ ȱ ȱ £ȱ ȱ Ƹŗǰȱ ȱ ǻǼȱ £ȱ
Ǽǯȱȱȱȱȱȱȱȱȱ¢ȱ
ȱȱ ȱȱDZȱ
ȱ
•
•
•
•
1
1
•
ȱ ȱȱǻŗşǼȱȱȱŚǯśȱȱȱǽƸŗǾȱȱ ȱȱ
•
ȱ ȱ Śǯśȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ûȱ ǽŖǾǰȱ ǽŗǾǰȱ ǯǯǯǰȱ ǽǾǰȱ ǽƸŗǾȱ ǯȱ ȱ ȱ ȱ ȱ
ȱǻȱǼȱ
ȱȱŚǯŜȱ ȱȱȱǽǾȱ§đȱǻŘŖǼȱ£ȱ
ȱ ȱ ȱ ȱ Śǯŝȱ ȱ ȱ ȱ ǻŘŖǼȱ ȱȱ ǽǾǽƸŗǾǰȱ ǽǾǽǾǰȱ
dzǰȱǽǾǽŖǾȱǯȱ
•
•
ȱȱ
ǽǾǽŖǾȱƽȱǽǾǽǾȱƽȱŗȱûȱŖȱ≤ȱȱ≤ȱƸŗȱ
ǽǾǽǾȱƽȱǽȬŗǾǽȬŗǾƸǽȬŗǾǽǾȱûȱȱŗ≤ȱȱ≤ȱƸŗǰȱŗȱ≤ȱȱǀȱȱȱȱȱȱȱ
ȱ
ȱȱřȱ ȱȱȱȱûȱŖǻǼȱȱǻǻŘǼƸǻŗŚǼǼȱ
ȱŚȱȱȱǰȱȱȱ ȱȱȱǽǾǽŖǾǰȱǽǾǽŗǾǰȱǯǯǯǰȱ
ǽǾǽƸŗǾǰȱǽǾǰȱŗȱ≤ȱȱ≤ȱȱûȱ ǰȱȱȱȱãȱûȱŗǰȱŘǰǯǯǯǰȱȱ
§đȱȱȱȱ
ŚǯŗȱȱŚǯŘDZȱȱûȱǽǾȱ ȱȱȱǻŗŝǼȱǯȱȱȱ
¢ǻǼȱ ȱ ȱ û£ȱ ȱ ȱ ȱ £ûǯȱ ȱ
ȱȱȱȱȱȱãđȱȱȱ
ȱȱȱ§ȱǰȱȱȱȱȱȱȱȱ
ȱ Śǯřȱ ȱ ȱ ûȱ ǽǾȱ ȱ ȱ ȱ ȱ ȱ ǻŗşǼȱ
ȱ ȱ ȱ ǻǼȱ ǻȱ ȱȱ ȱ £ ȱ ȱ ûȱ
Ǽȱ
¡§ȱȱ ȱȱǯȱȱ ¡§ȱȱȱȱ
ǻřǼȱ ǻȱ Śȱ ȱ ȱ ȱ ȬǼǰȱ ȱ ȱ ȱ ȱ
¢ǯȱ ȱ ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ Ȭ
ȱ£ȱǯȱȱ
ȱ £ȱ ȱ ǻǼȱ ȱ ȱ ȱ ȱ ȱ ȱ ûȱ ǯȱ ȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ãDZȱ ǻŖǼǰȱ
ǻŗǼǰȱǯǯǯǰȱǻȬŗǼǯȱȱȱȱȱȱȱȱȱûȱǻǼDZȱ
ȱ
Lösung ( Pk ) = Kombination( Lösung ( P0 ) ,Lösung ( P1 ) ,...,Lösung ( Pk −1 )) ȱ
ȱ
318
Grundlegende Algorithmen mit Java
ȱãȱȱȱǻǼȱȱȱȱãȱȱȱǻƸŗǼǰȱǻƸŘǼǰȱdzȱ
ǰȱ ȱ ȱȱãȱȱȱȱȱȱȱǰȱ
ȱ §ȱ ȱ ȱ ãđȱ ȱ ȱ £ȱ £ȱ ãǯȱ
ȱȱȱȱȱ¢ȱǯȱ
ȱ
A[k][0]
A[k][1]
A[k][2]
A[k][3]
A[k][4]
A[k][5]
0
0
0
0
0
1
1
1
0
-1
1
3
1
0
2
2
10
1
15
6
A[k][6]
M[k]
1
2
6
4
30
← ãȱȱƽȱŖ
← ãȱȱƽȱŗ
← ãȱȱƽȱŘ
← ãȱȱƽȱř
← ãȱȱƽȱŚ
← ãȱȱƽȱś
ȱ
§DZȱûȱȱ ȱ ȱȱȱȱȱ §ȱ ȱ ȱǰȱȱȱ
ȱ ûȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ȱ ȱ ȱ
§ǰȱȱȱȱȱȱǯȱ
Programm
import java.io.*;
import java.util.*;
public class P01SumOfPowers {
private static final String FileInputName = "psum.in";
private static final String FileOutputName = "psum.out";
private final static int MAX_NO = 20;
private static void genCombinations(long C[][], int n) {
C[0][0] = 1;
£ȱǻȱ
for (int i = 1; i <= n; i++) {
ǼDZȱ
C[i][0] = C[i][i] = 1;
§n·
for (int j = 1; j < i; j++)
¨ ¸ = 1, wenn k = 0 oder n = k
C[i][j] = C[i-1][j-1]+C[i-1][j]; ¨© k ¸¹
}
§ n · § n − 1· § n − 1·
¨¨ ¸¸ = ¨¨
¸¸ + ¨¨
¸¸, n > k , k ≠ 0
}
© k ¹ © k − 1¹ © k ¹
(ȱûȱȱ ȱȱ
¢ȱ)
public static void main(String args[]) throws IOException {
Scanner scanner = null;
PrintStream out = null;
try {
scanner = new Scanner(new File(FileInputName));
9
Potenzsummen
out = new PrintStream(new File(FileOutputName));
Fraction fr[] = new Fraction[MAX_NO+2];
Fraction W[] = new Fraction[MAX_NO+1];
long C[][] = new long[MAX_NO+2][MAX_NO+2];
genCombinations(C, MAX_NO+1);
long M[] = new long[MAX_NO+1], Q;
M[0] = 1;
long A[][] = new long[MAX_NO+1][MAX_NO+2];
A[0][1] = 1;
A[0][0] = 0;
for (int p = 1; p <= MAX_NO; p++) {
int sign = 1;
for (int t = p-1; t >= 0; t--) {
W[t] = new Fraction(sign*C[p+1][p+1-t], M[t]);
sign *= -1;
}
for (int t = p; t >= 0; t--) {
fr[t] = new Fraction();
for (int r = p-1; r >= t-1 && r >= 0; r--) {
fr[t].add(W[r].multiply(A[r][t]));
}
}
fr[p+1] = new Fraction(1, 1);
Q = Fraction.lcmDenomin(fr, p+1);
M[p] = (p+1)*Q;
for (int t = p+1; t >= 0; t--) {
A[p][t] = fr[t].multiply(Q).getNumerator();
}
}
while (scanner.hasNextInt()) {
int k = scanner.nextInt();
out.print(M[k]);
out.print(' ');
for (int t = k+1; t >= 0; t--) {
out.print(A[k][t]); out.print(' ');
}
out.println();
}
} finally {
if (scanner != null) scanner.close();
if (out != null) out.close();
}
}
}
319
320
Grundlegende Algorithmen mit Java
class Fraction {
private long numerator;
private long denominator;
Fraction(long numerator, long denominator) {
this.numerator = numerator;
this.denominator = denominator;
this.simplify();
}
Fraction() {
this.numerator = 0;
this.denominator = 1;
}
long getNumerator(){
return numerator;
}
void add(Fraction other){
this.numerator
= numerator*other.denominator +
denominator*other.numerator;
this.denominator = denominator*other.denominator;
this.simplify();
}
Fraction multiply(long n){
return
new Fraction(numerator*n, denominator);
}
private static long gcd(long a, long b) {
while (b != 0) {
ȱȱǻǼDZȱ
long r = a % b;
ȱ ȱ ãđȱ ȱ ȱ
a = b;
ǻǼȱ£ ȱûȱȱ
b = r;
}
return a;
}
void simplify() throws ArithmeticException {
long d = gcd(this.numerator, this.denominator);
this.numerator /= d;
Ȭȱ ȱ ȱ ãđȱ ȱ
this.denominator /= d;
ȱȱȱȱ§ȱȱ
if (this.denominator < 0) {
Ȭȱ û£ȱȱȱ
this.denominator *= -1;
Ȭȱ ȱ ƽƽŖǰȱ ȱ ¡ȱ
this.numerator *= -1;
ȱ
}
}
9
Potenzsummen
321
static long lcm(long a, long b) {
return (a/gcd(a, b))*b;
}
ȱ ȱ ȱ ȱ ȱ
ûȱȱȱȱȱȱȱ a ⋅ b ȱ
gcd( a, b)
static long lcmDenomin(Fraction fr[], int n) {
long gcd = 1;
ȱ ȱ ȱ
if (n == 0)
ȱȱȱ
return 1;
ǻǼȱ ȱ ȱ ȱ ûȱ ǽǾǰȱ
gcd = fr[0].denominator;
ȱȱȱDZȱ
for (int i = 1; i < n; i++) {
gcd = lcm(gcd, fr[i].denominator); ȱǻµµǼȱƽȱȱǻǻµǼµǼȱȱ
ȱ
}
ǻȱ ȱ ȱ §ȱ ȱ
return gcd;
£ȱ ȱ ǰȱȱ
}
ȱ ȱ ȱ ȱ £ȱ ãđȬ
}
ȱ£ȱ£ȱûǯǯǯǼȱ
Aufgaben
ŗǯ
Řǯ
ȱǰȱȱûȱřȱȱûȱȱǰȱǰȱȱDZȱȱȱǻµµǼȱƽȱ
ȱǻǻµǼµǼǯȱ
ȱȱǰȱȱȱ£ȱȱȱȱDZȱ
S k (n) = Fk +1n k +1 + Fk n k + ... + F1n + F0 ǰȱȱ
ȱ
ȱƸŗǰȱǰȱǯǯǯǰȱŖȱû£ȱûȱǰȱ£ǯǯDZȱȱ
n
S0 ( n) =
¦i = n ȱ
ȱ
0
ȱ
ȱ
ȱ
ȱ
i =1
n
S1 (n) =
¦ i = 2 n + 2 n ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
1
i =1
n
S 2 ( n) =
1
2
ȱ
¦ i = 3 n + 2 n + 6 n ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
2
1
3
1
2
1
i =1
ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ ȱ
ȱȱȱȱȱǯȱ
DZȱ
psum.in
2
5
0
ȱ
řǯ
psum.out
1/3 1/2 1/6 0
1/6 1/2 5/12 0 –1/12 0 0
1 0
ȱȱȱȱDZȱ
ȱȱȱȱȱȱȱǼȱ S3 ( x ) = ( S1 ( x)) 2 ȱ
322
Grundlegende Algorithmen mit Java
Ǽȱûȱȱȱ≥ȱŗȱDZȱȱ¢ȱ S k (x) ȱȱȱ S1 ( x) ȱȱȱ
S k ( x) = S k (−1 − x) ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ǻŘŘǼȱ
Ǽȱûȱȱȱȱ≥ȱŗȱDZȱȱ¢ȱ S k (x) ȱȱȱ S 2 ( x) ȱȱȱ
ȱ
S k ( x) = − S k (−1 − x) ȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ
ȱ
ǻŘřǼȱ
Ǽȱûȱȱȱ≥ȱřȱDZȱȱ¢ȱ S k (x) ȱȱȱ S3 ( x) ȱǯȱ
Ǽȱ ȱ S k ( n) = ak +1n k +1 + ak n k + ... + a1n + a0 ȱȱ ak − 2 = ak − 4 = ... = 0 ǯȱȱ
DZȱ ȱ ãȱ ȱ £ȱ £ ȱ S k (x) ȱ ȱ S k ( − x) ȱ ȱ ȱ ȱ
ǻŘŘǼȱȱǻŘřǼȱǯȱ
ȱ
ȱ
ȱ
ȱ ȱôȱȱȱ§ȱ
ȱ
ȱ
ȱ
ȱȱȱȱȱȱȱȱǯȱȱ
ȱ ¢ȱ
ȱ
Literaturverzeichnis
ȱ
ȱ
ǽŖŘǾȱ
ǽŞřǾȱ
ǽşřǾȱ
ǽşŚǾȱ
ǽŝŗǾȱ
ǽŖŚǾȱ
ǽŖŖǾȱ
ǽşşǾȱ
ǽŖŘǾȱ
ǽşŜǾȱ
ǽ şŗǾȱ
ǽ ŝşǾȱ
ȱǰȱ ûȱǯȱǰȱȱ ȱȱ ǰȱȱȬ
ǰȱŘŖŖŘǯȱ
ȱǰȱȱȱ©ȱȱȱȱ©ȱ ǰȱ
ȱ©ȱóȱ©ǰȱóǰȱŗşŞřǯȱ
¢ǰȱǯȱǯǰȱȱ¢ ǯȱȱǰȱȱȱ ǯǰȱ
ǰȱŗşşřǯȱ
ǰȱ ǯǰȱ ǰȱ ǯǰȱ Ȭ ȱ ȱ ȱ Ȭ ȱ Ȧǰȱ ȱ Ȃȱ
ȱȱ ȱ ȱǰȱŗşşŚǯȱ
ǯȱ ǯǰȱ ǯǰȱ ȱ ¡¢ȱ ȱ Ȭȱ ǰȱ ǯȱ řȱ Ȭ
ȱȱ¢ǯȱ¢ȱȱǰȱǯȱŗśŗȬŗśŞǯȱ
ǯȱ ǯȱǰȱǯȱǯȱǰȱǯȱǰȱǯȱǰȱȬȱȬ
ûǰȱȱǰȱûǰȱŘŖŖŚǯȱ
ȱǰȱ ǰȱȬǰȱ ǰȱŘŖŖŖǯȱ
ǰȱǯǰȱǰȱǯǰȱ¡ȱȂȱȱȱȱȱ
ȱ ȱ ǰȱ ȱ ȱ ȱ ȱ ǯǰȱ ǯȱ řŖřȬřŖŜǰȱ
ŗşşşȱ
ȱ ǰȱ ȱ ȱ ȱ ǯȱ ȱ ȱ ȱ ǰȱ Ȃȱ ¢ǰȱ
ǰȱŘŖŖŘǯȱ
ȱ ǰȱ ȱ ǰȱ ȱ ǰȱ ǰȱ
ŗşşŜǯȱ
ȱ ǰȱ ȱ óȱ ȱ ȱ ©ǰȱ ȱ ©ǰȱ
óǰȱŗşşŗǯȱ
¢ǰȱǯȱǯǰȱȱ ǰȱǯȱǯǰȱȱȱȱ ¢DZȱȱ ȱȱȱ
¢ȱȱȬǰȱȱǯȱ ǯȱǰȱ ȱȱǯȱ
324
ǽ Ǿȱ
ǽ şŚǾȱ
ǽ ŖřǾȱ
ǽ ŖŘǾȱ
ǽ şŝǾȱ
ǽ şşǾȱ
ǽ ûŖŜǾȱ
ǽŖŗǾȱ
ǽŖśǾȱ
ǽŖśǾȱ
ǽŖśǾȱ
ǽŖŜǾȱ
ǽŖŜǾȱ
ǽŖŜǾȱ
ǽŖŜǾȱ
ǽŖŝǾȱ
ǽ§ŖŗǾȱ
Grundlegende Algorithmen mit Java
£ȱ©ǰȱȱ£ǰȱȱȱ
ȱ ǯȱ ǯǰȱ ȱ ǯȱ ǯǰȱ ȱ ǯǰȱ ȱ ǰȱ
Ȭ¢ǰȱŗşşŚǯȱ
ȱ ǰȱ ȱ ǯȱ ûȱ ȱ ȱ ȱ ȱ
ȱ ¢ȱ £ȱ ǰȱ Řǯȱ ǰȱ ȱ ǰȱ Ȭ
ǰȱŘŖŖřǯȱ
ȱ óǰȱ ȱ ©ǰȱ ôȱ ǰȱ ȱ ©ǰȱ
ȱ ƸƸǯȱ ȱ ȱ ȱ ȱ Ȭǰȱ ȱ ǰȱ óǰȱ
ŘŖŖŘǯȱ
ȱǯȱ ǰȱȱȱȱȱǰȱȱ DZȱȬ
ȱ ǰȱ Ȭ¢ȱ ǰȱ Dzȱ DZȱ řǯȱ ǯǰȱ
ŗşşŝǯȱ
ȱǯȱ ǰȱȱǯȱǰȱȱǯȱ Ȭ
ǰȱǰȱȱǯǰȱȱǰȱŗşşşǯȱ
ȱ ûǰȱ ȱȱ ȬǰȱŚǯǰȱȱȬ
ǰȱȬ¢ǰȱûǰȱŘŖŖŜǯȱȱ
ȱ ©ǰȱ ƸƸǯȱ ȱ £ȱ óȱ ǰȱ ȱ ǰȱ
óǰȱŘŖŖŗǯȱ
ȱ ©ǰȱ ȱ ȱ ǰȱ ǰȱ ŗśȦŘȱ ŘŖŖśǰȱ ǯȱ ŚŖȬŚřǰȱ
DZȱDZȦȦ
ǯǯȦȦŗśȏŘȦŘǯǯȱ
ȱ ©ǰȱ kȱ ȱ ǰȱ ǰȱ ŗśȦśǰȱ ŘŖŖśǰȱ ǯȱ řŜȬŚŗǰȱ ȱ DZȱ
DZȦȦ
ǯǯȦȦŗśȏśȦŗǯǯȱ
ȱ©ǰȱȱȱȱȱȱȱȱȱȱƸƸǰȱ
ǰȱŗśȦśǰȱǯȱŘŝȬřŖǰȱDZȱ
DZȦȦ
ǯǯȦȦŗśȏśȦŗǯǯȱ
ȱ©ǰȱ£ȱ©ȱÉȱǯȱôǰȱȱǰȱ óǰȱ
ŘŖŖŜǯȱ
ȱ ©ǰȱ ȱ ǰȱ ȱ ¢ȱ ȱ ȱ ȱ
ȱ ȱ ȱ ȱ ǰȱ řȱ ȱ ȱ ȱ
ȱȱȱǻ ǼǰȱȱřşŖŝǰȱǯȱřŘŖȬřřŗǰȱ
ǰȱŘŖŖŜǯȱ
ȱ©ǰȱ ¢ȱȱȱȱȱȱȱ ȱȱ
ȱ ǰȱ ȱ ȱ ȱ ȱ ŘŖŖŜǰȱȱ ¢Ȭ
ȱȱȱǰȱǯȱŜśȬŞŖǰȱ óǯȱ
ȱ ©ǰȱ ȱ ȱ ãȱ ȱ ƸƸǰȱ Ȭ
ǰȱǰȱŘŖŖŜǯȱ
ȱ ©ǰȱ ȱ ȱ Éȱ ƸƸǯȱ ôǰȱ ǰȱ óǰȱ
ŘŖŖŝǯȱ
ȱ đȱ §ǰȱ ȱ ȱ ǯȱ ȱ ǯǰȱ
ûǰȱŘŖŖŗǯȱ
Literaturverzeichnis
ǽŖŘǾȱ
ǽşśǾȱ
ǽşŝǾȱ
ǽşŞǾȱ
ǽ©ŞřǾȱ
ǽŖŚǾȱ
ǽşŞǾȱ
ǽşŝǾȱ
ǽşşǾȱ
ǽŖřǾȱ
ǽşŝǾȱ
ǽŞŜǾȱ
ǽŜŜǾȱ
ǽŜŝǾȱ
ǽŖŜǾȱ
ǽŞŗǾȱ
ȱ
325
ǯȱ ñǰȱ ǯȱ ñìǰȱ ȱ ǯȱ ȱ ǰȱ
ȱǰȱŘŖŖŘǯȱ
ǰȱǯǰȱǰȱǯǰȱ ǰȱǯȱǯǰȱȱȱȱȱȬ
ǰȱȱ Ȃȱȱȱȱ¢ǯǰȱŗşşśǯȱ
ǰȱ ǯǰȱ ǰȱ ǯǰȱ ǰȱ ǯȱ ǯǰȱ ȱ ȱ ȱ Ȭ
ȱǰȱȱ ȱ Ȃȱǯȱȱ ǰȱŗşşŝǯȱ
ǰȱǯǰȱǰȱǯǰȱǰȱǯǰȱȱȱȱȬ
ȱȱ£ȱǰȱȱȱȱǯǰȱǯȱŜşŚȬŜşŝǰȱŗşşŞǯȱ
ǯȱ ©©ǰȱ ǯȱ ô©ǰȱ ǯȱ ǰȱ ǯȱ ôǰȱ ¡ôȱ óȱ ȱ ȱ
©ǰȱȱ©ȱóȱ©ǰȱóǰȱŗşŞřǯȱ
ȱ £ǰȱ ȱ ûȱ ǯȱ ȱ ȱ ȱ ȱ ȱ Ȭ
ǰȱ ȱǰȱǰȱŘŖŖŚǯȱ
£Ȭȱ ǰȱ ȱ ûǰȱ ȱ ǰȱ ȱ ȱ
ǯȱǰȱ ȱȱȱ ǰȱŗşşŞȱ
ȱǰȱȱǯȱȱȱȱ ȬǰȱȱȱȬ
ǰȱǰȱŗşşŝǯȱ
ȱ ǰȱ ȱ ǯȱ ȱ ǰȱ ȱ ȱ
ǰȱǰȱŗşşşǯȱ
ȱ ǯȱ ǰȱ ȱ ǯȱ ǰȱ ȱ ǯȱ ȱ Ȭ
ȱȱȱǰȱȬǰȱ ȱǰȱŘŖŖřǯȱ
ǰȱǯǰȱ ȱȱȱ¢ȱȱǰȱȬ ǰȱǰȱ
ǯȱ
ǯȱǰȱǯȱǰȱȱǰȱȬǰȱ Ȭ
ǰȱŗşŞŜǯȱ
ȱǰȱûȱȱȱãȱǰȱȱ DZȱ ǰȱ
ǯȱǰȱûȬǰȱŗşŜŜǯȱ
ȱǰȱûȱȱȱãȱǰȱȱ DZȱȱȬ
ȱ ȱ ȱ §ǰȱ ǯȱ ǰȱ ûȬǰȱ
ŗşŜŝǯȱ
ȜȱǰȱȱȱŜȱ ȱǰȱȱ£DZȱ
DZȦȦǯǯȦȦŜȦȦȦǰȱȱ¢ǰȱ ǰȱŘŖŖŜǯȱ
ȱ ǰȱ ȱ ȱ ©ȱ óȱ ȱ ǰȱ ȱ
©ȱóȱ©ǰȱóǰȱŗşŞŗǯȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
326
Grundlegende Algorithmen mit Java
ȱ£ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱDZȦȦǯ ǯȦ Ȧ ȱ
ȱDZȦȦǯǯȦȦȱȱ
ȱDZȦȦǯǯǯȦȱȱ
ȱDZȦȦ ǯ ǯȦȱȱ
ȱDZȦȦ¢ǯǯȦȦȦȦȱȱ
ȱDZȦȦ¢ǯ ǯǯȦȦȱȱ
ȱDZȦȦ
ǯǯȦȱȱ
ȱDZȦȦ
ǯ ǯȦȱȱ
ȱDZȦȦ
ǯȬȬǯȱ
ȱDZȦȦ
ǯǯȦȱȱ
ȱDZȦȦǯǯȦDžřȦŖǯȱȱ
ȱDZȦȦǯȦȬȦȱȱ
ȱDZȦȦ
ǯǯǯȦȦȦŘǯȱ
ȱDZȦȦ
ǯǯȱ
ȱDZȦȦ
ǯȬǯȱ
ȱDZȦȦ
ǯȬǯȦǯȱ
ȱDZȦȦ
ǯǯǯȦ ȦŘŖŖŜȦŖŜŖŘŗŚȏǯȱȱ
ȱDZȦȦ
Ȭŗǯǯ ȬǯȦDžȱ
ȱDZȦȦ
ȬǯǯȦDžȦȦǯȱ
ȱDZȦȦǯǯȦȦŜȦȦȦȦȦ¢ǯȱ
ȱDZȦȦǯȦȬȦ ȦȦǯȱ
ȱDZȦȦ
ǯǯȬȱ
ǯȦȦŘŖŖřȦ¢ȦȦŖřŖşǯȱ
ȱ
ȱ
ȱȱȱ
ȱ
ȱ
Stichwortverzeichnis
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
řȬȬȱȱŘřŘȱ
̋ȬȱȱŗŘȱ
̛Ȭȱȱŗřȱ
ƋȱȱŗŗŚǰȱŗŜśȱȱȱ
A
ȱȱŗŖŜȱ
absȱȱŗŝŚǰȱŗŞŗǰȱŗşŖǰȱŘŝŝȱ
ȱȱȱŘŚŖȱȱ
ȱȱŗŗȱ
ȱ ȇȱ ȱ ȱ ȱ Ȭ
£ȱȱŗȱ
§§ȱȱřŜȱ
ǰȱȱȱŗŗŞȱȱ
ȱȱŗŗŞȱ
addȱȱŚŘǰȱśŚǰȱŜŖǰȱşŗǰȱŗřŗǰȱŗřŚǰȱŗŚŖǰȱŗŚŝǰȱŗŜśȱ
addFirstȱȱşŗȱ
addLastȱȱşŖȱȱȱ
£ȱȱŘŘŘȱȱȱ
££¡ȱȱŞǰȱŜŞǰȱŘŘŘȱȱ
§ȱȱȱŘŜŗȱȱȱ
ȱŗŖǻǼȱȱ
ȱǻǼȱȱŘşȱ
ȱ ȏǻǼȱȱŘŞŞȱȱȱ
ȏȏ ȱȱŗŝŜȱȱȱ
ȏȏȱȱŗŝŜȱȱ
ȏ ȏ ȱȱśȱȱ
ȏȏ ȱȱŘŞŝȱȱȱ
ȏ ȱȱŗŚŜȱ
ȏŗŖȱȱŗŘŗȱȱȱ
ȏ ȱȱŘȱ
ȏ ȏ ȱȱŝŚȱ
ȏȱȱŗŜřȱȱȱ
ȏ ȱȱŘřřȱ
ȏȱȱŘřřȱ
ȏ ¢ȱȱřşȱȱ
ȏ ȏȱȱŘŗŘȱ
ȏ ȱȱśşȱ
ȏ ȱȱśŗȱ
ȏȱȱŘŚŜȱȱ
ȏȏȱȱŗŝřȱȱ
ȏ ȏȱȱŞŖȱȱ
ȏ ȏȱȱŝŞȱȱ
ȏ ȏȏȱȱŘŖŞȱȱȱ
ȏȱȱřŗŜȱ
ȏȏȱȱŝřȱ
ȏȏ ȱȱŝřȱ
ȏȱȱŝşȱȱ
ȏŘȱȱŞŖȱ
ȏ ȏ ȱȱŗŖŞȱȱ
ȏ ȏ ȱȱŚȱ
ȏȱȱŝşȱ
ȏ ȱȱŜȱ
ȏ ȏ ȱȱŘŞȱ
ȏ ȏ ȱȱřŖŝȱ
ȱǻǼȱȱȱȱŗŜŚȱ
ȱȱȱȱȱŝśȱȱ
ȱȱŗŖȱ
Ȭȱȱŗȱ
ȱȱŗŖȱ
allocateȱȱŘŚŘǰȱŘŝŘȱ
¢ȱȱ ¡§ȱȱŗŜȱ
£ȱȱ ȱȱŗŞŗȱ
328
£ȱȱȬȱȱŗŝŞȱ
£ȱȱȱȱŗŝşȱ
£ȱ ȱ ȱ ûȱ ȱ Ȭ
ȱȱřŖŚȱ
£ȱȱ £ȱ¡ȱȱŗśŞȱ
£ȱȱȱȱȱŗŞŜȱ
£ȱȱȱȱȱȱŗŖŝȱ
£ȱȱûǰȱûȱȱ ȱȱŗśŖȱȱ
£ȱ§ȱ§§ȱȱŜřȱ
appendȱȱřśǰȱŗŗŖǰȱŗŜŖȱ
ȱȱřŖśȱ
ArithmeticExceptionȱȱřŘŖȱ
arraycopyȱȱŞŖǰȱŞŝȱ
ArrayDequeȱȱŞřǰȱŞşȱ
ArrayListȱȱŚŗǰȱśŘǰȱśŚǰȱŜŖǰȱşŗǰȱŗŚŜǰȱŗśŚǰȱŗŜśȱ
ArraysȱȱřŖǰȱřřȱ
asListȱȱřřȱ
assertȱȱřŖǰȱřŜȱ
AssertionErrorȱȱřŜȱȱȱ
ȱȱŘřŞȱȱȱ
ȱȱȱŘŝǰȱŘŚŖȱ
ȱȱřŚȱ
¢ȱȱřŚȱ
ȱŗŖŖȱ
ȱȱȱȱşŚȱȱȱ
B
ȱȱŗŜşǰȱŘřśȱ
ǰȱǰȱȱȱ ȱȱŘŘŜȱ
ȱȱȱȱȱŘŘŞȱȱ
ȱȱŚşǰȱŗŖśǰȱŗśŝǰȱŘřřȱ
ȱȱǵDZȱȱŚřǰȱŜŘǰȱŗŘŜǰȱŗŚŝǰȱŗŜŗǰȱ
ŘŖşǰȱŘśśȱ
ȱȱŘśǰȱŗŝŘȱ
ǰȱȱȱŘřŗȱ
ȱ£ȱȱŗŜşȱȱȱ
ȱȱȱŗŖśȱ
ȱȱŗŖȱȱ
ȱȱȱȱȱŘřŗȱ
ȱȱŗŗǰȱŗŖŖǰȱŗŖşǰȱŗŗŗǰȱŗŘŞǰȱŘŚŖȱ
ȱ ȱ §ȱ ȱ ȱ ŗŖŗǰȱ
ŗŖřȱȱȱ
££ǰȱ¡ȱȱŗŜşȱ
BigDecimalȱȱŗŗŚȱ
Grundlegende Algorithmen mit Java
BigIntegerȱȱŗŗŗǰȱŘřşȱȱ
ȱȱȱŗŞȱ
§ȱȱśŜȱȱȱ
§ȱȱȱŚȱ
§ ȱȱśŜǰȱŜśȱȱȱ
£ȱȱŘřśǰȱŘřşǰȱŘŝřǰȱřŗŞȱȱȱ
ȱ £ȱ ǻ Ȃȱ Ȭ
ǼȱȱŗŖŘǰȱřŗŘȱȱȱ
Ȭȱ
BitSetȱȱŞŚǰȱŘŖŗǰȱŘŗŞȱ
ȱȱśŜȱ
BooleanȱȱŜŘǰȱŞşȱ
ȬȬ£ȱȱŘřŚȱ
ȬȬȱȱŜŜȱȱ
C
P ] 164ȱȱ
·ȱȱȱŘŗŚȱȱ
§ǰȱ ȱȱŗŚśȱȱȱ
ȬȱȱŜřǰȱŘŘŚǰȱŘŝśǰȱŘŞŜǰȱŘşŘȱ
catchȱȱřŗǰȱřŚȱȱȱ
¢Ȭ £Ȭȱ ǻ £Ȭ
ȱǼȱȱŗŖŘȱ
CharacterȱȱŘŗŝȱ
charAtȱȱŜŖǰȱŗŜŖǰȱŘŖşǰȱřŖŘȱ
clearȱȱŞŝǰȱŘŖřǰȱŘŗŖǰȱŘŗşȱ
cloneȱȱŘŖřȱȱȱ
closeȱȱřŗǰȱŚŘǰȱŚśǰȱŚŞǰȱśŚǰȱŜŗǰȱşŚǰȱŗŗŖȱ
Ȭȱȱŗşȱȱ
ȱȱȱ§ȱȱśŜȱ
ȱȱȱ§ȱȱśŜȱ
£ȬȱȱŗŖŜǰȱŗŘśȱ
CollectionsȱȱŚŖǰȱŚŘȱȱȱ
ȏȱȱŘŗŗȱ
ComparableȱȱŘşǰȱřřǰȱŚŘǰȱŜŗȱ
compareȱȱŚřȱ
compareToȱȱřŖǰȱřřǰȱŚŖǰȱŚřǰȱŜŘȱ
ȱȱȱŗŖŜǰȱŗŗŞȱ
ǰȱȱǰȱǯȱǯȱȱŘŖȱ
currentTimeMillisȱȱŘřŝȱȱȱ
D
ȱȱŝǰȱřŘǰȱŗŘŗȱ
Stichwortverzeichnis
ȱȱȱȱŜśȱȱȱ
ȱȱřŘǰȱŚŖǰȱŗŜřǰȱŘśśǰȱřŗşȱ
ȱȱŜśȱ
ȱȱ £ȱȱ ȱŗŜŝȱ
Ȭ ȱȱřŘȱ
ȱȱśŜȱ
deleteȱřŖřȱ
DequeȱȱŞŘǰȱŞşȱ
ȱȱŗŖȱȱ
ȱȱȱŘȱȱ
ȱȱŚȱȱŗŖŞȱ
digitȱȱŘŗŝȱ
DimensionȱȱŗřŗǰȱŗřřǰȱŗřŞȱȱȱ
ȱȱȱŗŖŜǰȱŗřŖȱȱ
ȱ ȱȱŗŖŖǰȱŗŖŘǰȱŗŖşǰȱŗŗŗǰȱŗŘŞȱȱȱ
ȱ Ȭȱ ǻǼȱȱ
ŗŜŘȱ
ȱȱ ȱȱŗŚśȱȱ
ȱȱȱȱŗŗŗȱȱ
ȱȱŘśřȱ
ȱȱûȱȱŗŜŞȱ
ǰȱ ȱȱŜŜǰȱŝŗȱ
DoubleȱȱśŘȱ
ȱȱȱȱŞŘȱ
drawLineȱȱŗřşȱ
drawOvalȱȱŗřřȱ
drawRectȱȱŗřŗǰȱŗřŚȱ
ȱȱŜŝȱȱ
Ȭ §ȬȱȱŝŞȱ
¢ȱȱȱŘŝǰȱŘřŗȱȱȱ
E
Ȭ£ȱȱŘşŝȱȱȱ
£ȱȱŗŜŘȱ
ȱȱȱŗŗȱ
ȱȱŗŖȱ
ȱȱŗŖŜȱ
enstrySetȱȱśśǰȱŜŖǰȱşŘȱȱȱ
ȱȱŗŞǰȱŝŘȱ
ȱȱ ¢ȱȱřȱ
ûȱȱŘŖȱ
ȱȱȱşśȱ
ȱ ȱȱşŜȱ
ȱȱŘȱȱȱ
329
ȱȱȱŘŞŞȱȱ
ȱȱȱŘǰȱřŘŖȱ
ǰȱȱȱŗŜŚǰȱŘŗŚȱ
¡ȬȱǻǼȱȱŝŚȱ
EXIT_ON_CLOSEȱȱŗřŗǰȱŗřŚȱȱȱ
¡ȬȱȱŜŜȱ
F
ȱȱȱǻǼȱȱȱ
ȱȱȱŗŖŜǰȱŗŘřȱ
ȱǻȱǼȱȱŘřŜȱȱȱ
ȬȱȱŗŖśǰȱŘřŘȱ
FileȱȱřŖǰȱřśǰȱŚŗǰȱŚŚǰȱśřǰȱŜŖǰȱŗŗŖȱ
FileReaderȱřśȱ
fillȱȱřŗǰȱŘśşǰȱŘŝŝȱȱȱ
finallyȱȱřŗǰȱřŚǰȱŚśǰȱdzǰȱŗŗŖǰȱdzȱ
FloatBufferȱȱŘŝŘȱ
flushȱȱŘřŞȱ
Ȭȱ ȱ śŚǰȱ ŜŘǰȱ şŖǰȱ ŗŜŜǰȱ ŗŝŚǰȱ ŗŞŝǰȱ
ŘŖŚǰȱŘŗŖǰȱŘŚŘǰȱŘŜŖǰȱŘŝŝȱ
FormatterȱȱŗŘřȱ
ȱȱŗśŞȱ
ȱȱŗşŗȱ
ȱȱŗřśȱȱȱ
ȱȬȱȱŗŚŗȱ
G
gcdȱȱŗŗŗȱ
£ȱȱřŘȱ
ȱȱŘŖŞǰȱřŗŝȱ
ȱȱŗřśȱ
ȱȱȬȱȱŞŖȱ
ȱȱȬȱȱŝŞǰȱŗŝŖȱ
ȱȱȱȱŗŝşȱ
ȱȱȱŗŘŞȱ
£ȱȱȱȱŜŝȱ
getȱȱŚŘǰȱśŘǰȱŜŖǰȱşŗǰȱŗŚŝǰȱŗŜśǰȱdzǰȱŘŗŖǰȱŘŚŘȱ
getContentPaneȱȱŗřŗǰȱŗřŚǰȱŗŚŖȱ
getDefaultToolKitȱȱŗřŗȱ
getFirstȱȱşŗȱ
getKeyȱȱśśȱ
getLastȱȱşŗȱ
getScreenSizeȱȱŗřŗȱ
330
getSizeȱȱŗřŗǰȱŗřřǰȱŗřŞǰȱŗŚŖȱ
getValueȱȱśśǰȱŜŗȱ
ȱȱ ȱȱŚşȱ
ȱȱ Ȭȱȱśŝȱ
ȱȱ ȱȱŚşȱ
¢ȱȱǰȱȱȱřŞȱ
ȱȱŗŖŘǰȱŗŘřǰȱŘŘśǰȱŘŞŗȱ
ȱȱȱȱřŗŖȱȱȱ
ȱȱşǰȱŗŞǰȱŚŞǰȱŝśǰȱŘřřȱ
§ȱȱŘŖȱ
ȱȱŘŖȱȱ
GraphicsȱȱŗřŗǰȱŗřřǰȱŗřŞȱ
¢ȱȱřşǰȱŘřśȱ
¢ȬȬȱǻ ǼȱȱŝŚȱ
¢ȬȬȬȱ ǻ Ǽȱȱ
ŝŚȱ
¢ǰȱ ȱȱŗŗŚȱ
£ ȱȱŗŚȱ
ãđȱȱȱȱŘǰȱŗŚŜǰȱřŘŖȱ
H
ȱȱŗşȱȱȱ
Ȭ£ȱȱŜŜǰȱŘşŞȱ
ȱȱŗŞǰȱřşȱ
HashSetȱȱŘŖŗȱ
hasNextȱȱśśǰȱŜŖǰȱŘŗşȱ
hasNextDoubleȱȱŗśŘǰȱŗŜŜȱ
hasNextFloatȱȱŚŘȱȱȱ
hasNextIntȱȱřŖǰȱřśǰȱŗŗŖǰȱŗŗŜǰȱŗŘŚǰȱŗŚŝǰȱŗśŚȱ
hasNextLongȱȱŗŗşǰȱŗŘŗǰȱŗŘŜǰȱŘŞŚȱ
hasPreviousȱȱŜŗǰȱŘŚşȱȱȱ
ȱȱȱȱŘŘŗȱ
heightȱȱŗřŗǰȱŗřřǰȱŗřŞȱ
ǰȱǯȱǯȱǯȱȱŗśřȱ
£ȱȱȱȱȱŘřŖȱ
ǰȱȱȱśŜȱ
ȬȱȱśŜȱ
Ȭ ȱȱśŜȱȱȱ
I
§ȱȱȱŗȱ
§ȱȱŗŜŘȱȱȱ
ȱȱȱŗŖŜǰȱŗřřȱ
Grundlegende Algorithmen mit Java
ȱȱŗŖŖȱ
ȱȱŗŖŖȱ
£ȱȱŗŖŖȱ
ȱȱŗřśȱ
insertȱřŗǰȱřśǰȱřŖřȱȱȱ
IntBufferȱȱŘŚŗȱ
Integer śŘǰȱŜŖǰȱŞşǰȱdzǰȱŗśŚ
Integer.MAX_VALUEȱȱŚŝǰȱŘśŞǰȱŘŝŜȱȱȱ
ȱȱŗśŖȱ
ȱȱřřȱ
intersectsȱȱŘŖŚȱ
intValueȱȱśřǰȱşŖȱ
ȱȱŜŜȱ
IOExceptionȱȱŚŗǰȱŚŚǰȱŚŝǰȱśřǰȱŜŖǰȱşřǰȱŗŗŗȱ
isDigitȱȱŘŗŝȱ
isEmptyȱȱśśǰȱŜŖǰȱŘŖŚȱ
ȱȱŗŞȱ
isProbablePrimeȱȱŗŗŗȱ
IteratorȱȱśŚǰȱŜŖǰȱşŗȱ
iteratorȱȱśśǰȱŜŖǰȱşŗȱȱȱ
J
JFrameȱȱŗřŗǰȱŗřŚǰȱŗřşȱ
JPanelȱȱŗřŗǰȱŗřřǰȱŗřŞȱ
K
ȱȱȱȱŘŚȱ
ȱȱřŘȱȱȱ
§ȱȱŝǰȱŚřǰȱŘŘŚȱȱȱ
ȱǻǼȱȱȱȱŗŜŚȱ
ȱȱȱŘŘśȱ
ȬȬȱȱŘřŞȱȱȱ
keyȱȱśřǰȱşřȱȱȱ
ȱȱ¢ȱȱŜřȱȱȱ
ȱȱȱ ȬȱȱŘŘŚȱ
£ȱȱȱȱŗŞȱȱ
ȱȱȱȱřŘŗȱ
ȱôȱȱřŘŘȱ
ǰȱ ȱȱȱŗřśȱ
Ȃȱȱȱŗřśȱ
ȱȱśŜȱȱȱ
ȱȱŗŞŗȱ
£Ȭȱȱşřȱȱ
Stichwortverzeichnis
ȱȱŘŖŜȱȱ
ȱȱȱŘŖŜȱȱ
ȱȱȱŘŖŜȱȱȱ
¡ȱȱȱŗŜŘȱȱȱ
¡§ȱȱŗŖǰȱŗŘǰȱŚŗǰȱśşǰȱŝŚǰȱŗśřǰȱŗśśǰȱŘŖŞǰȱ
ŘřŚǰȱřŗŝȱȱ
ȱȱǻ ǼȱȱŘŗȱ
ȱ ȱȱŗŘȱȱ
ȱȱŘşǰȱřŘȱȱȱ
¡ȱ ûȱȱŗśȱ
ȱȱŗŘŝǰȱŗřŜȱ
ȱȱŗŖȱȱȱ
ǰȱȱ ȱȱŗşȱ
ǰȱ ȱȱȱśŗȱȱ
ȬȱȱŚŞǰȱŞřȱ
L
¢ȱȱŘŘŞȱ
§ȱȱȱȱŘŚŖȱȱȱ
§ȱȱȱȱŘŝǰȱŘŚŖȱȱȱ
§ȱȱȱȱŘŚśȱ
£ȱȱŗŚȱ
£ǰȱ ȱȱȱŗŗŚȱ
lengthȱȱŞśǰȱŗŜŖǰȱŘŖşǰȱŘŝŝȱȱȱ
ǰȱȱȱŘşŞȱ
Ȭ£ȱȱŘşŞȱ
¡ȱȱŘŝǰȱŝŞǰȱŗŝşǰȱŘŘŗǰȱŘŞŞȱ
ȱȱȱŘřŜȱȱ
ȱȱȱŗŖŜǰȱŗŗśȱ
ListȱȱŚŗǰȱśŘǰȱŜŖǰȱşŗǰȱŗŚŝǰȱŗśŚȱ
ListIteratorȱȱśŚǰȱŜŗǰȱşŗǰȱŘŚşȱ
listIteratorȱȱśśǰȱŜŗǰȱşŘǰȱŘŚşȱ
LocaleȱȱŚŗǰȱśřǰȱŗŘŚȱ
ȱȱȱŘŗǰȱŞŘȱ
LongȱȱŗŘŖȱ
Long.MAX_VALUEȱȱŘşśȱ
ȱȱȱŝŜȱ
ǰȱȱȱŗŚŞȱ
ȬȱȱŘřŞȱȱȱ
ȱ ǯǰȱ ãȱȱŗŚśȱ
M
ǰȱ ȱȱŗŗśȱ
331
ȱȱȱŗŜşǰȱŗŝŝȱȱȱ
ȬȬȱȱŗŘŖȱȱȱ
ȱȱȱȱŝȱ
Map.EntryȱȱśŚǰȱŜŖǰȱşŗȱ
Math.absȱȱŗŝŚǰȱŗŞŗǰȱŗşŖǰȱŘŝŝȱ
Math.cosȱȱŗŜśȱ
Math.maxȱȱśŚǰȱşřȱ
Math.minȱȱśřǰȱşřǰȱŗřŗǰȱŗřřȱ
Math.PIȱȱŗŜśȱ
Math.powȱȱŘŞşȱ
Math.randomȱȱŞśȱ
Math.roundȱȱŘřŞȱ
Math.sinȱȱŗŜśȱ
Math.sqrtȱȱŗřŞǰȱŘŞşȱ
maxȱȱśŚǰȱşřȱ
¡ȱȱȱȱŘŜȱ
ȱȱřřȱȱȱ
£ȱȱŘřŘȱȱ
ûȱȱŘŖȱȱ
ȱȱŗŚŜǰȱŗśśȱ
ȱȱŜŝǰȱŘşŝȱ
ȬȱȱŘşŞȱ
minȱȱśřǰȱŗřŗǰȱŗřřȱȱȱ
ȱȱȱŘŞŜȱȱȱ
ȱȱȱŚşǰȱŝŜȱ
ȱȱȱȱŗřŜȱ
ȱȱȱȱȱŗŘȱ
modPowȱȱŗŗŗȱ
ȱȱŝśȱ
Ȭ £ȱȱśŘǰȱŞřȱȱȱ
ȱȱ£ȱȱŘşŗȱȱȱ
ȱȱŘşřȱȱȱ
N
ȬȱȱŝŞȱ
ûȱȱȱřřǰȱŚŗȱ
ǰȱ£ǰȱǯȱȱŗŜşȱ
ȬȬȱȱŗŜşȱȱȱ
ȬȱȱȱŘśȱȱȱ
nextȱȱśśǰȱŜŖǰȱŘŗşȱ
nextBooleanȱȱŞśȱ
nextClearBitȱȱŞŝȱ
nextDoubleȱȱśŘǰȱŗŘŚǰȱŗśŘǰȱŗŜŜȱ
nextFloatȱȱŚŘǰȱřŖŞȱ
332
nextIntȱ ȱ řŖǰȱ řśǰȱ ŚŚǰȱ Śŝǰȱ ŜŖǰȱ ŗŗŖǰȱ ŗŗŜǰȱ ŗŘŘǰȱ
ŗřşǰȱŗŚŝǰȱŗśŚǰȱŗŝŚǰȱŗŞŜǰȱŗşŖǰȱŗşŘȱ
nextLongȱȱŗŖŞǰȱŗŗřǰȱŗŗşǰȱŗŘŘǰȱŗŘŜǰȱŘŞŚȱ
ȱ ȱ ǻǼȱ ȱ ȱ ŗŖŜǰȱ
ŗŘśȱ
ȬȱȱŘŗȱ
Ȭ§ȱȱŗşǰȱŝŗȱ
ȬûȬȱȱŗŝŞȱ
NullPointerExceptionȱȱřřȱȱȱ
O
ȱȱȱŗřȱ
ȱ ǻȱ Ǽȱ ȱ ȱ ŗŖŜǰȱ
ŗŘśȱ
Ȭȱȱŗřȱ
§ȱȱŗśǰȱŘřŗȱȱȱȱ
§£ȱȱŘřŗȱ
ȱȱŗŞȱ
ȱȱŗşŜȱȱȱ
[ȱȱŞȱ
ȱȱřŘȱȱȱ
ȱȱřŘȱ
P
packȱȱŗřŗǰȱŗřŚǰȱŗŚŖȱ
paintȱȱŗřŗǰȱŗřřǰȱŗřŞȱ
parseIntȱȱşřȱ
ȱȱûȱȱȱŗŞŘȱȱȱ
ȱãȱȱŘŚŚȱȱȱ
ȬȱȱŘśȱȱ
ǰȱ ȱȱşşȱȱȱ
ȱ¡ȱȱşşȱȱȱ
ȱȱŘśǰȱŜŝǰȱŝŝȱȱȱ
ȱǻƋǼȱȱŗŗŚǰȱŗŜśȱȱȱ
ǰȱȱǻǼȱȱŘřŜȱȱȱ
Ȭȱȱŗśřȱ
Ȭȱȱŗśŝȱ
¢ȱȱŘŞŜȱȱȱ
¢ȱřŘȱȱȱ
¢ȱȱŗŜřǰȱŘŞŘǰȱřŗŖȱ
positionȱȱŘŚŘȱȱȱ
£ǰȱȱȱŗŖŝȱȱȱ
£ǰȱȱȱŗŖŞȱ
Grundlegende Algorithmen mit Java
£ȱȱřŗŗȱȱ
powȱȱŘŞşȱȱ
§¡ȱȱśŜȱȱȱ
ȬȱȱȱŗśŞȱ
previousȱȱŘŚşȱ
£ȱȱřŘŗȱȱȱ
£ȱȱřǰȱŗŖŗȱ
printȱȱřŗǰȱřŜǰȱŚŗǰȱŚŘǰȱŚśǰȱŜŘȱ
printfȱȱŚŞǰȱśŚǰȱşŚǰȱŗŗŜȱ
printlnȱȱřŗǰȱřŜǰȱŚŘǰȱŚŞǰȱśŚǰȱŗŗŖǰȱŗŗřȱ
printStackTraceȱȱřŗǰȱřŚȱ
PrintStreamȱȱŚśǰȱŚŝǰȱŜŖǰȱşřǰȱŗŗŖǰȱŗŗřȱ
PrintWriterȱȱřŖǰȱřśȱȱ
ȱȱȱûȱȱȱȱȱȬ
ȱȱŗŝşȱȱȱ
ȱȱȱûȱȱȱ
ȱȱȱȱŗŞŖȱ
¡ȱȱŘşŘȱ
putȱȱśŘǰȱśŚǰȱŜŖǰȱşŗǰȱŘŚŘǰȱŘŝŘȱȱȱ
Q
Ȭ§ȱȱŗśŝȱȱȱ
ȬȱȱŘřŞȱȱȱ
ȱȱŗŘŝǰȱŗśŞȱ
ȱȱȱȱŗŖŜȱ
ȱȱŗŚŜǰȱŗśŘȱ
R
ȱǻȱȱǼȱȱŗŗȱ
RandomȱȱŞŚȱ
randomȱȱŞśȱ
ûȱȱȱŗŚŗȱ
ȱȱŗŜŘȱ
ȱȱŗśŘȱȱȱ
ȱȱŗŖśȱ
ȱȱŗśȱȱȱ
ȱȱȱŗŝȱ
ȱȱşşȱ
ȱȱŘŜŞǰȱřŗřȱ
ȱȱŘŜŞǰȱřŗřȱ
ȱȱȱŗŖśȱ
ȱ ȱȱŗŘŖȱ
ȱ£ȱȱŗŖŝȱ
Stichwortverzeichnis
removeȱȱśśǰȱŜŗǰȱŗŝŝǰȱŘŗŖȱ
replaceȱȱřŖŘȱȱȱ
ȱđȱ£ȱȱŗŗŗȱ
£ȱȱŜȱ
roundȱȱŘřŞȱȱȱ
ȱȱŘŖǰȱŚŖȱ
§ȱȱŘŘȱȱȱ
S
ȱȱŘŖȱ
£ȱǻĘǰȱ£ǼȱȱŘŚŖȱȱȱ
£ȱȱȱǻȱǼȱȱŗŘřǰȱŘŞŘȱ
ScannerȱȱřŖǰȱřśǰȱŚŗǰȱŚŚǰȱŚŝǰȱśřǰȱŜŖǰȱŗŖŞȱ
ȬȱȱŗŖǰȱŘŖȱ
ȱȱȱȱƸŗȱȱşşȱȱ
ȱ£ȱȱŗŖŞȱ
ȱ ȱ ȱ ȱ ȱ ȱȱ
ŗśȱ
ȱȱȱȱȱŘŜŜȱ
§ȱȱȱ ȱȱŗŚřȱ
£ȱȱǻ¢Ȭ
£ȬǼȱȱŗŖŘȱ
SetȱȱŘŖŗȱ
setȱȱŞŝǰȱŘŖřȱ
setDefaultCloseOperationȱȱŗřŗǰȱŗřŚȱ
setLocationȱȱŗřŚǰȱŗŚŖȱ
setPrefferedSizeȱȱŗřŗǰȱŗřŚǰȱŗŚŖȱ
setVisibleȱȱŗřŗǰȱŗřŚǰȱŗŚŖȱȱ
ȱȱȱȱřȱȱȱ
ȬȱȱŗŚŖȱ
sizeȱȱŜŖǰȱşŖǰȱŗŚŝǰȱŘśśȱ
ȱȱȱȱȱȱȱřřŚȱ
sortȱȱřŖǰȱřřǰȱŚŖǰȱŚŘȱ
ȱŘŝȱ
ȬȱȱȱŗŚŗȱ
ȱȱŚşȱȱȱ
ȱȱȱȱŗŖŜȱ
ȱȱȱȱȱŚśǰȱŗŞŞǰȱŘŝśȱ
sqrtȱȱŗřŞǰȱŘŞşȱ
ȱȱ ȱȱřřǰȱȱŘśśǰȱŘŞşȱ
ȱȱȱȱşŞȱ
ãȱȱ¢ȱȱřŖşȱ
StringȱȱŚŗǰȱŚŚǰȱŚŜǰȱśřǰȱŜŖǰȱŗŗŖȱ
StringBufferȱȱřśȱ
333
StringBuilderȱȱřŗǰȱřśǰȱŗŗŖǰȱŗŜŖǰȱřŖŗȱ
substringȱȱřŖŘȱ
ȱȱŘŗŚȱ
ȱ£ ȱ£ȱȱŗŘřȱȱȱ
ȱȱȱȱŘŞŖȱ
ȱȱŗŜǰȱŗŖŖǰȱŗŖŚǰȱŗŝŝȱȱȱ
ȱȱȱŗŞśȱȱȱ
ȱȱŝŞȱ
¢ȱ ȱȱŝǰȱŞȱ
¢ȱȱŜŝǰȱŗŘşȱ
System.inȱȱŗŝŚǰȱŗŞřǰȱŗŞŜǰȱŗşŖǰȱŘŜşȱȱ
T
ȱȱŗŖŗǰȱŗŖśǰȱŗşşȱ
ȱȱȱ£ȱȱŗŖŗȱ
ȱȱŗśşȱ
ȱȱŘŗŚȱ
ȱȱ ȱȱŗŚśȱȱȱ
ȱŗŖŗǰȱŗŖśǰȱŗşşȱ
ȱȱŘŚśȱ
ȱȱŗŚśǰȱŘřŗȱȱȱ
ȱȱŘŖśȱ
ThrowableȱȱřŗǰȱřŚȱ
ȱȱŜȱ
ToolkitȱȱŗřŗǰȱŗřŚȱ
Ȭ Ȭ£ȱȱŘřŚȱ
toStringȱȱŚŖǰȱŚřǰȱŗŘŗǰȱŗŜŜǰȱŘśśȱ
ȱȱŝȱ
ȱȱŜŜȱ
£ȱȱŗśŖȱ
ȱȱȱǻǼȱȱŗŞȱȱ
TreeMapȱȱśŘǰȱŜŖǰȱşŗȱ
ȱ ȱ ¡ȱ ¢ȱȱ
ŘŞŜȱȱȱ
ȬȱȱŘřŞȱ
tryȱȱřŖǰȱřŚǰȱdzǰȱŗŗŖȱ
ȱ ȱ ȱ ǯȱ §ȱȱ
ŜŚȱȱȱ
ûȱȱ ȱȱŗŖśǰȱŗŚŞȱȱ
U
ûȱȱȱřŘȱ
ûȱȱȱřŘȱ
334
tȱȱȱȱŘřŘȱ
ûȱȱȱŗŚȱ
ȱȱȱŗřȱȱȱ
ȱȱŚŞȱ
£§ǰȱ ȱȱŚşȱ
useLocaleȱȱŚŗǰȱśřǰȱŗŘŚǰȱŗśŘȱ
V
valueȱȱśřǰȱşřȱ
ȱȱřŘŖȱȱȱ
ȱȱŘŖȱ
ȱȱȱŗŖŜǰȱŗŗŞȱȱȱ
ȱȱȱŘśȱ
£ȱȱśŝȱ
ȱȱȱŘŘşȱ
ȱȱ ȱȱŘśŞȱȱ
£ ȱȱȱŗŖŜǰȱŗŘřȱȱȱ
ȱȱřŘŗȱȱ
ǰȱȱȱǯȱȱřŘŗȱȱȱ
ȱȱǻ£ȱȱǼȱȱŗŘřǰȱŘŞŘȱȱȱ
§ȱ ȱȱşşȱȱ
§ȱ§ȱȱśŜȱ
§ȱ ȱŝśȱȱ
Grundlegende Algorithmen mit Java
ȱȱśŜȱ
ȱȱśŝȱ
ȱȱŗŗȱȱȱ
ȱȱŗşŞȱ
§ȬãȬȱȱŝřȱ
£§ǰȱ ȱȱŚşȱ
ȱȱŜȱ
ȱȱŜŞȱȱȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
ȱ
W
ȱȱǻǻǼǼȱȱŗŝȱ
ȱȱŘŜŞȱȱȱ
ȱȱŚşȱ
ȱȱȱȱđȱȱŗŚŚȱȱȱ
ȬȱȱŚŜȱ
ȱȱŘŜǰȱŘŚŖȱ
widthȱȱŗřŗǰȱŗřřǰȱŗřŞȱ
WindowConstantsȱȱŗřŗǰȱŗřŚȱ
Ȭȱ¡¢ȱȱŗŚȱȱȱ
Ȭ ȱȱŗŘŖȱȱ
ȱȱû£ȱȱŘŜŜȱ
££ȱȱȱȱŗŘřǰȱŘŞŘȱ
Z
ȬȱȱŘŚşȱȱȱ
¢ȱȱŗŘŖȱȱȱ
ǰȱȱȱŗŘŖȱȱȱ
ȱ
ȱ
ȱȱȱȱȱȱ
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )