Knights tour - results in an infinite loop and i can't figure out why

允我心安 提交于 2019-12-02 01:11:35

Your algorithm seems to work just fine, yielding correct results for smaller problem instances, like a 5x5 or 7x7 board. It seems like the 8x8 board is just too big for the brute force / backtracking approach.

Still, you can simplify your findTour method, making it easier to understand and to debug:

public boolean findTour(int x, int y, int c) {
    solutionBoard[x][y] = c;
    if (c == size*size) {
        return true;
    }
    for (Point p : MOVES) {
        Point dst =  new Point(x + p.x, y + p.y);
        if (canMove(dst) && findTour(dst.x, dst.y, c + 1)) {
            return true;
        }       
    }
    solutionBoard[x][y] = -1;
    return false;
}

Example-Output for findTour(0, 0, 1) with size = 7 (need to adapt all code to variable size!)

 1 14  3 38  5 34  7 
12 39 10 33  8 37 26 
15  2 13  4 25  6 35 
40 11 32  9 36 27 44 
19 16 21 24 45 48 29 
22 41 18 31 28 43 46 
17 20 23 42 47 30 49    

Still better: Use one of the other algorithms mentioned in the Wikipedia article, for example the rather simple Warnsdorff heuristic: "We move the knight so that we always proceed to the square from which the knight will have the fewest onward moves." We can achieve this by sorting the moves...

public Point[] sortedPoints(final int x, final int y) {
    Point[] sorted = Arrays.copyOf(MOVES, MOVES.length);
    Arrays.sort(sorted, new Comparator<Point>() {
        public int compare(Point p1, Point p2) {
            return Integer.signum(nextMoves(p1) - nextMoves(p2));
        };
        private int nextMoves(Point p) {
            Point dst = new Point(x + p.x, y + p.y);
            if (canMove(dst)) {
                int s = 0;
                for (Point m : MOVES) {
                    Point dst2 = new Point(dst.x + m.x, dst.y + m.y);
                    if (canMove(dst2)) {
                        s++;
                    }
                }
                return s;
            } else {
                return 999;
            }
        }
    });
    return sorted;
}

... and changing the successors-loop to for (Point p : sortedPoints(x, y)). Results:

size     findTour calls without and with heuristic
5x5                     76497       25 
7x7                     8947880     49
8x8                     ???         64
20x20                   ???         400

Indeed, for all the sizes I tried, the findTour method was called exactly size^2 times, i.e. it found the tour on first try, without backtracking at all.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!