Java 解决骑士巡游需要很长时间

huangapple go评论71阅读模式
英文:

Java solving Knights tour takes very long

问题

public class Springerproblem {
    private final int xDelta[] = {1, -1, 1, -1, 2, -2, 2, -2};
    private final int yDelta[] = {2, 2, -2, -2, 1, 1, -1, -1};
    private int[][] springerFeld;
    private int n0;

    public int[][] springer(int n, int x, int y) throws NoSolutionException {
        springerFeld = new int[n][n];
        this.n0 = n;

        if (spring(x, y, 1)) {
            return springerFeld;
        } else {
            throw new NoSolutionException();
        }
    }

    private boolean spring(int x, int y, int zugnummer) {
        springerFeld[x][y] = zugnummer;
        if (zugnummer == n0 * n0) {
            return true;
        }
        for (int i = 0; i < xDelta.length; i++) {
            int newX = x + xDelta[i];
            int newY = y + yDelta[i];
            if (loesbar(newX, newY, zugnummer + 1)) {
                springerFeld[newX][newY] = zugnummer + 1;
                if (spring(newX, newY, zugnummer + 1)) {
                    return true;
                }
            }
        }
        springerFeld[x][y] = 0;
        return false;
    }

    private boolean loesbar(int x, int y, int zugnummer) {
        if (0 <= x && x < n0 && 0 <= y && y < n0 && springerFeld[x][y] == 0 && spring(x, y, zugnummer + 1)) {
            return true;
        }
        return false;
    }
}

(Note: The translation provided above is a direct translation of the code without any changes to method names or logic.)

英文:

Hey so i gotta code an algorithm for the Springerproblem (https://upload.wikimedia.org/wikipedia/commons/8/86/Knight%27s_tour.svg)

My code is currently endlessly running at a field of 6x6

We got a Junit class to test it. a field of 3x3 with the starting positions of x=1 and y=1 is working just fine.

public class Springerproblem {
private final int xDelta[] = {1,-1,1,-1,2,-2,2,-2};
private final int yDelta[] = {2,2,-2,-2,1,1,-1,-1};
/**
* Datenstruktur zum Abspeichern der Springerzuege
*/
private int[][] springerFeld;
private int n0;
/**
* Gibt ein zweidimensionales, quadratisches int-Array zurueck. 
* n ist die Schachbrettbreite.
* Der Springer startet an Position (x,y) mit 0&lt;=x,y&lt;n.
* Auf den jeweiligen Postionen des Arrays sind die Positionen des 
* Springers eingetragen. Die erste Position traegt die 1.
* Wenn sich das Problem nicht loesen laesst, so wird eine 
* NoSolutionException geworfen.
*/
public int[][] springer(int n, int x, int y) throws NoSolutionException{
springerFeld = new int[n][n]; //erzeuge neues Spielfeld
this.n0 = n; // &#252;bernehme n
if (spring(x, y, 1)) { //rekursionsende wird im Stack als letztes abgebaut zugNr ist dabei 1 also die Startposition
return springerFeld;
}
else {
throw new NoSolutionException();
}
}
private boolean spring(int x, int y, int zugnummer) {
springerFeld[x][y] = zugnummer;//Zugnummer ist am Anfang 1
if(zugnummer == n0*n0) { //dann ist es am Zeil und teilt methode springer mit dass es fertig ist
return true;
}
for(int i = 0; i &lt; xDelta.length; i++) {
int newX = x + xDelta[i]; //neue Position x
int newY = y + yDelta[i]; // neue Position y
if(loesbar(newX, newY, zugnummer+1)) { // wenn die n&#228;chste Position frei ist 
springerFeld[newX][newY] = zugnummer+1; // f&#252;ge sie zum weg hinzu
if(spring(newX, newY, zugnummer+1)) { //rekursionsaufruf mit der n&#228;chsten Position
return true;
}
// backtracking
}  
}
springerFeld[x][y] = 0;
return false;
}
private boolean loesbar(int x, int y, int zugnummer) {       
if(0 &lt;= x &amp;&amp; x &lt; n0 &amp;&amp; 0 &lt;= y &amp;&amp; y&lt; n0 &amp;&amp; springerFeld[x][y] == 0 &amp;&amp; spring(x, y, zugnummer+1)) {
return true;
}
return false;
}
}

Also the method names etc. cannot be changed

答案1

得分: 1

你的算法是正确的。但是你的 loesbar() 方法不应该调用 spring(...),否则你的算法每一步都会花费两倍的时间。

此外,尝试的步骤顺序对于寻找单个解决方案来说并不是最优的。这个问题在这里有相同的问题:https://stackoverflow.com/questions/20783702/knights-tour-backtracking-lasts-too-long

使用不同顺序的步骤可以更快地找到第一个解决方案:

    private final int xDelta[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
    private final int yDelta[] = { 1, 2, 2, 1, -1, -2, -2, -1 };

这里有一个解释:https://stackoverflow.com/questions/21511683

英文:

Your algorithm is correct. But your loesbar() method should not call spring(...), else your algorithm spends twice the time each step.

Also the sequence of steps to try is not optimal for finding a single solution.
This question had the same issue: https://stackoverflow.com/questions/20783702/knights-tour-baktracking-lasts-too-long

Using a different sequence of steps finds a first solution more quickly:

    private final int xDelta[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
private final int yDelta[] = { 1, 2, 2, 1, -1, -2, -2, -1 };

An explanation is given here: https://stackoverflow.com/questions/21511683

huangapple
  • 本文由 发表于 2020年4月3日 21:00:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/61012493.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定