java 骑士巡游问题-移动顺序影响性能

qhhrdooz  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(117)

我试图实现一个骑士游问题的解决方案。我遇到了一个有趣的问题。我想知道行为的原因。
这是代码-它工作正常。

public class OpenKnightTour {

    private int[][] chessTable;
    private int startRow;
    private int startCol;
    private int ChessBoardSize;

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

    public OpenKnightTour(int ChessBoardSize, int startRow, int startCol){
        this.ChessBoardSize = ChessBoardSize;
        this.startRow = startRow;
        this.startCol = startCol;
        this.chessTable = new int[ChessBoardSize][ChessBoardSize];
    }

    void move(){
        //first move
        this.chessTable[this.startRow][this.startCol] = 1;

        //start with 2nd move recursively
        moveHelper(this.startRow, this.startCol, 2);

        //print results
        this.print();

    }

    private boolean moveHelper(int r, int c, int count){
        if((count-1) == (this.ChessBoardSize * this.ChessBoardSize))
            return true;

        for(int[] move: moves){
            int nextR = r + move[0];
            int nextC = c + move[1];
            if(isMoveValid(nextR, nextC)){
                chessTable[nextR][nextC] = count;
                if(moveHelper(nextR, nextC, count + 1)){
                    return true;
                }
                chessTable[nextR][nextC] = 0;
            }
        }
        return false;
    }

    private void print(){
        Arrays.stream(this.chessTable)
                .forEach(a -> System.out.println(Arrays.toString(a)));
    }

    private boolean isMoveValid(int r, int c){
        if(!(r >= 0 && r < this.ChessBoardSize))
            return false;
        if(!(c >= 0 && c < this.ChessBoardSize))
            return false;
        return chessTable[r][c]==0;
    }

}

现在我们可以运行它,从矩阵中的马位置(2, 2)开始

OpenKnightTour o = new OpenKnightTour(8, 2, 2);
    o.move();

当我试着运行(0, 0)的起始位置时,它一直在运行,没有显示任何结果。所以我认为它不可能有任何解决方案。但是如果我稍微改变一下下面的顺序,它马上就工作得很好。

private final int[][] moves = {
        {-1, -2},
        {-2, -1},
        {-2, 1},
        {-1, 2},
        {1, -2},
        {1, 2}, //moved from last 
        {2, -1},
        {2, 1},
};

到底是怎么回事?,这个动作的位置怎么会对表现有这么大的影响?,那么在这种情况下,我们怎么知道正确的动作顺序呢?

gzjq41n4

gzjq41n41#

你正在一个非常大的搜索空间中进行暴力搜索,如果你的搜索方式不好,你可能会花很长时间找不到解决方案。
答案是,要么你在起点/起点模式的选择上很幸运,要么你需要更聪明地认识到“无可救药地卡住了”。
例如,每回溯10,000次,扫描整个棋盘。如果你能找到你不可能回到的洞,然后设置一个标志,使你回溯到你可能访问过它的最后一步。然后继续。这让你跳过一大块潜在的无用工作,回到寻找many possible tours中的一个。

相关问题