英文:
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<=x,y<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; // ü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 < 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ächste Position frei ist 
springerFeld[newX][newY] = zugnummer+1; // füge sie zum weg hinzu
if(spring(newX, newY, zugnummer+1)) { //rekursionsaufruf mit der nächsten Position
return true;
}
// backtracking
}  
}
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;
}
}
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论