Autor Beitrag
Jake10
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 26



BeitragVerfasst: Sa 01.09.07 22:48 
Hallo,
... es geht um das Springerproblem (Ein Springer soll auf einem Schachfeld jedes Feld genau einmal besucht haben), wobei bei meinem Lösungsversuch Fehler aufgetreten sind und ich nicht genau weiß wie man die behebt:
Also zu Beginn bin ich mal Schritt für Schritt durchgegangen (z.B. bei Feldgröße 6 mal 6). Am Anfang gab es keine Probleme. Doch als ich zurück gelaufen bin (-->backtracking), da der Springer in einer Sackgasse landete, habe ich das Feld markiert und hab auf der einen anderen Weg (nicht den markierten Weg auf der nächsthöheren Ebene) gewählt und hab von da an das Backtracking gemacht. Nur leider endet der Algorithmus von mir in einer Endlosschleife ("stack Überlauf"). Ich glaube ich setze die Markierung nicht richtig, sodass er immer den gleichen falschen Weg geht. Blöderweise bin ich nicht in der Lage das Problem zu beheben.
Könnt ihr mir vielleicht helfen?
Ich wäre euch sehr sehr dankbar.
(Ich hoffe ihr kommt mit dem umständlichen Quelltext zu Rande...)
Einloggen, um Attachments anzusehen!
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: So 02.09.07 08:00 
Guten morgen,

Du machst da was völlig falsch, uups schlecht geschlafen .... ;-)

Was deinen Pogram fehlt ist die Speicherung von Zaehler1 zu jedem Feldpunkt.
Du benutzt Zaehler1 global, bei jeden Schritt zurück wird nicht ein neuer Weg versucht sondern wieder bei 1 begonnen..
Feld: array of array of boolean sollte statt boolean einfach die Zaehler1 beherbergen.
Wenn das Feld 0 ist war dort noch kein Springer, sonst steht dank Zaehler1 in welche der 8 Richtungen er gesprungen ist.
Dein Array of char ist eigentlich doppelt gemoppelt, da diese Information schon in Feld ist.

Um einigermassen vernünftig damit klar zu kommen, mußt Du Dir auch den Weg selber merken.
Du brauchst also eine Liste (array) der Grösse der Anzahl der Spielfelder=sqr(Anzahl2) in der die Koordinaten des x-ten Zuges gespeichert sind.
Der erste Zug kann ja immer 1/1 sein, der Starpunkt sein.
Jetzt zum vorgehen.
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
IniTialisieren:
Alles auf 0 setzten.
Startbedingungen vorgeben
Du bist beim Zug (Zaehler2) nr 1:
In der Liste der Züge das die Koordinaten dort 1,1 eintragen.
Jetzt in Feld[Liste(Zaehler2).X,Liste(Zaehler2).Y] Zaehler1 = 1 für dieses Feld eintragen.

Jetzt Baktracking:
Schaue in der Liste bei Zaehler2 (=ZugNr) nach den aktuellen Koordinaten K_akt und dort nach Zaehler1(=neueRichtung).
wiederhole:
Falls Zugnr = 0 then
  Alle Züge durchprobiert-> habe Fertig
Falls ZugNr = MaxZuege dann
  neue Lösung gefunden-> Ausgeben und zaehlen
  ZugNr verkleinern und weiter machen(eigentlich kann wohl ??Züge direkt zurückgehen)

//Weiter machen
  Teste ob von K_akt=Liste[ZugNr] aus in neueRichtung ein Sprung möglich ist(Feld innerhalb Spielfeld und unbelegt(=0)).
  Falls ja dann 
    erhöhe ZugNr und trage die Koordinaten in die Liste ein, belege diese Koordinaten mit neueRichtung=1.
    //Dieses Backtracking geht eine zug weiter
    Backtracking,
  sonst
    erhöhe Feld[K_akt] um 1 (neueRichtung)
    //alle Möglichkeiten durchprobiert
    Falls Feld[K_akt] > 8 dann
       //erst Feld freigeben
       Feld[K_akt] = 0
       //einen Zug zurückgehen
       ZugNr = ZugNr-1
   sonst
    //Dieses Backtracking geht in eine neue Richtung(das paasirt aber nur, wenn man einen Zug zurücknimmt
      Backtracking,


Ich hoffe das ist unverständlih genug

Gruß Horst
Fiete
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 617
Erhaltene Danke: 364

W7
Delphi 6 pro
BeitragVerfasst: Mi 17.10.07 15:47 
Moin Jake,
das Springerproblem läßt sich iterativ nach a) der Warnsdorff-Regel lösen oder b) rekursiv.

a)Im Jahr 1823 schlug H. C. Warnsdorff eine heuristische Regel vor,
die das Finden einer Lösung stark vereinfacht. Nach der Wansdorffregel
zieht der Springer immer auf das Feld, von dem aus er für seinen nächsten
Zug am wenigsten freie (d.h. noch nicht besuchte) Felder zur Verfügung hat.
Diese Regel ist unmittelbar einleuchtend, sie verhindert beispielsweise,
dass eines der beiden Felder, die der Springer von einer Ecke aus erreichen
kann, frühzeitig besucht wird, so dass der Springer später nicht mehr aus der
Ecke entkommen kann.
Die Warnsdorffsregel gibt keine Anweisung, was zu tun ist, wenn es mehrere
Felder gibt, von denen es gleich wenige im nächsten Zug erreichbare Felder gibt.

b)Auf dem Brett wird vom Startfeld in allen 8 Richtungen ein mögliches Zielfeld berechnet,
ist das Zielfeld leer, wird die Zugnummer reingespeichert und die Suche geht mit dem nächsten Wert weiter.
Gibt es kein leeres Zielfeld wird der Zug rückgängig gemacht.

procedure TSpringerRek.Springe(Zug,XAlt,YAlt:Integer);
var K,XNeu,Yneu:Integer;
begin
if Abbruch then exit; // Aussprung aus der Rekursion
inc(Versuch);
for K:=1 to 8 do
begin
XNeu:=XAlt+WA[K];Yneu:=YAlt+SE[K];
if Brett[XNeu,Yneu]=0 then
begin
Brett[XNeu,Yneu]:=Zug; // Zug ausführen
if Zug=NSqr then Ausgeben
else Springe(Zug+1,XNeu,Yneu);
Brett[XNeu,Yneu]:=0; // Zug rückgängig machen
end
end;
end;

Die dritte Variante gilt für Bretter der Länge 4K+1: immer an der Wand lang (s.Anhang)

Gruß, Fiete
Einloggen, um Attachments anzusehen!
_________________
Fietes Gesetz: use your brain (THINK)