fakult¨at f¨ur informatik

Werbung
TECHNISCHE UNIVERSITÄT MÜNCHEN
FAKULTÄT FÜR INFORMATIK
Lehrstuhl für Sprachen und Beschreibungsstrukturen
Einführung in die Informatik I für Ingenieure
Prof. Dr. Helmut Seidl, A. Flexeder, S. Friese, M. Petter
WS 2010/11
Übungsblatt 6
24.11.10
Abgabe: 05.12.10 (vor 12 Uhr)
Aufgabe 6.1 (P) Inverse Telefonbuchsuche
Es seien zwei Arrays a und b gegeben. Array a enthält Namen (Datentyp String). Array
b speichert zu jedem Namen eine Telefonnummer (Datentyp int). Die Telefonnummer zu
einem Namen befindet sich an der selben Position in Array b wie der Name in Array a.
Schreiben Sie ein Programm, das beide Arrays aufsteigend nach der Telefonnummer sortiert. Schaffen Sie die Möglichkeit, dass der Benutzer mit Hilfe der Telefonnummer nach
einem Namen suchen kann. Implementieren Sie dazu eine binäre Suche auf dem sortierten
Telefonbuch.
Aufgabe 6.2 (P) Türme von Hanoi
In dieser Aufgabe lösen wir das Rätsel der Türme von Hanoi :
Versetze einen Turm, der aus n unterschiedlich grossen Scheiben besteht, von einem
Startplatz zu einem Zielplatz. Für das Versetzen eines Turms steht ein Zwischenlager zur Verfügung. Pro Zug darf nur eine Scheibe bewegt, d.h. von einem Platz
zu einem anderen Platz verlegt werden. Zudem darf niemals eine grössere Scheibe
auf eine kleinere Scheibe gelegt werden!
Schreiben Sie ein Programm, welches der Reihe nach Anweisungen ausgibt, von welchem
Stapel man eine Scheibe auf welchen anderen Stapel bewegen muß, wenn man einen Turm
nach obigen Regeln versetzen will.
Für eine einzelne Scheibe ist die Lösung ganz einfach. Die Lösungsstrategie für einen Stapel
der Höhe n besteht darin, zuerst davon auszugehen, dass man Türme der Höhe n − 1 bereits
regelgerecht versetzen kann, und darauf aufbauend dann eine Lösung für Türme der Höhe
n zu konstruieren.
Beispiel:
a) Wir wollen den Turm von Lager 1 nach Lager 2 bewegen.
Als Zwischenlager wählen wir 3.
b) Bewege n − 1 Scheiben vom Startplatz (1) zum Zwischenlager (3). Verwende dazu den Zielplatz (2) temporär als
Zwischenlager.
c) Bewege die ehemals unterste Scheibe vom Startplatz (1)
zum Zielplatz (2), und gib diese Aktion via write aus.
d) Bewege nun die n − 1 Scheiben vom Zwischenlager (3) zum
Zielplatz (2). Verwende dazu den Startplatz (1) als temporäres Zwischenlager.
Wenden Sie dieses Verfahren rekursiv auf Türme an, die aus mehr als einer Scheibe bestehen. Definieren Sie dazu eine Methode void versetze(int n, int startplatz, int
zielplatz, int zwischenlager), die einen Turm der Höhe n von einem Startplatz startplatz über ein Zwischenlager zwischenlager zu einem Zielplatz zielplatz versetzt.
2
Aufgabe 6.3 [4 Punkte] (H) Schatzkiste
Ein Schatzgräber hat eine Schatztruhe voller wertvoller Schätze entdeckt. Leider kann er
die Truhe nicht alleine schleppen und muss so die Schätze in seinem Rucksack verstauen.
Jedes der gefundenen Schmuckstücke hat ein bestimmtes Gewicht und einen bestimmten
Wert. Der Schatzgräber möchte seinen Rucksack nun so packen, dass der Rucksackinhalt
das Maximalgewicht, das der Schatzsucher schleppen kann, nicht überschreitet und er durch
die mitgenommenen Schmuckstücke einen maximalen Wert erzielt.
Implementieren Sie ein optimales Packen des Rucksacks unter Verwendung rekursiver Funktionsaufrufe. Geben Sie am Ende Ihres Programms den Inhalt des gefüllten Rucksacks, sowie
dessen tatsächliches Gewicht und seinen Wert aus.
Das Gewicht und den Wert der einzelnen Schmuckstücke der Schatztruhe, liefert Ihnen die
Methode int[][] getTreasure(int n) der Klasse Schatz, wobei in der ersten Spalte des
n×2 Arrays das Gewicht des Schmuckstücks und in der zweiten Spalte dessen Wert abgelegt
ist. Der Parameter int n gibt die Anzahl der gefundenen Schmuckstücke der Schatztruhe
an. Schreiben Sie ein Programm Rucksack mit einer main-Methode, welche für einen Schatz
den Wert und den Inhalt des Rucksacks ausgibt.
Aufgabe 6.4 [6 Punkte] (H) Sudoku
Schreiben Sie ein Programm namens Sudoku.java, welches das Spiel Sudoku implementiert.
Die Grundregeln dieses Spiels sind folgende:
Ein Sudoku-Feld besteht aus 9 × 9 Feldern, die zusätzlich in 3 × 3 Blöcke mit 3 × 3 Feldern aufgeteilt sind.
Ausgangspunkt ist ein Sudoku-Feld in dem bereits Zahlen eingetragen sind. Ziel ist es, jede leere Zelle mit einer Zahl von 1 bis 9 so zu füllen, dass folgende Invariante
gilt:
Invariante: Jede Zeile, jede Spalte und jeder Block
enthält jeweils alle Zahlen von 1 bis 9 höchstens
genau einmal. (*)
Verwenden Sie die Klasse SudokuProvider.java, die Ihnen die statische Methode int[][]
fuelleFeld(int n) zur Verfügung stellt. Der Rückgabewert dieser Methode ist ein 2dimensionales Array, welches ein Sudoku-Feld repräsentiert, wobei Zellen entweder unbelegt
sind (d.h. den Wert 0 haben) oder bereits mit einer Zahl zwischen 1 und 9 unveränderlich
vorbelegt sind. Der Parameter n bedeutet, dass das Sudoku-Feld mit n zufälligen Zahlen in
zufälligen Feldern gefüllt werden soll.
Gehen Sie zur Implementierung von Sudoku wie folgt vor:
a) Definieren Sie eine Funktion boolean testeFeld(int[][] sudoku, int i, int j),
die false zurückgibt, falls der Eintrag in Zelle (i, j) zur Verletzung der Invariante (*)
führt (d.h. dass der Wert in Zelle (i, j) in der i-ten Spalte, j-ten Zeile oder in dem
jeweiligen Block ein weiteres Mal vorkommt).
b) Schreiben Sie eine Funktion loeseFeld(int[][] feld, int i, int j), die versucht
die Zelle (i, j) im Feld feld der Reihe nach mit Einträgen von 1 bis 9 zu füllen. Sobald ein gültiger Eintrag gefunden wurde, soll loeseFeld rekursiv für die nächste Zelle
aufgerufen werden. Falls loeseFeld false zurückgibt, sollen die eventuell verbleibenden Möglichkeiten, um Zelle (i, j) zu belegen, durchprobiert werden (inkl. rekursivem
Abstieg). Falls das nicht zum Erfolg führt, soll (i, j) wieder auf 0 zurückgesetzt und
false zurückgeben werden. Beachten Sie dabei die vorgegebenen unveränderlichen
Zellen, die Methode fuelleFeld bereits vorbelegt hat! Geben Sie am Ende das urspüngliche Sudoku-Feld und, falls möglich, eine Lösung aus.
c) Erweitern Sie Sudoku so, dass es die Anzahl der verschiedenen Lösungen ausgibt.
Herunterladen