Knight's Tour 代码陷入无限循环,无法解决

Posted

技术标签:

【中文标题】Knight\'s Tour 代码陷入无限循环,无法解决【英文标题】:Knight's Tour code runs into infinite loop, does not reach a solutionKnight's Tour 代码陷入无限循环,无法解决 【发布时间】:2018-12-25 06:22:29 【问题描述】:

我对 Knight's Tour 的递归回溯方法陷入了无限循环。起初,我认为这个问题通常可能会花费这么多时间,但有些解决方案会立即解决。请告诉我的代码有什么问题。

package io.github.thegeekybaniya.InterviewPrep.TopTopics.Backtracking;

import java.util.Arrays;

public class KnightsTour 
    private static int counter=0;

    public static void main(String[] args) 

        knightsTour(8);
    

    private static void knightsTour(int i) 
        int[][] board = new int[i][i];
        for (int[] arr :
                board) 
            Arrays.fill(arr, -1);

        
        board[0][0] = 0;
        knightsTour(board,0,1);

    

    private static boolean knightsTour(int[][] board, int cellno, int stepno) 
        if (stepno == board.length * board.length) 
            printBoard(board);
            return true;
        

        int[][] dirs = 
                1, 2, 1, -2, -1, 2, -1, -2, 2, 1, 2, -1, -2, 1, -2, -1
        ;
        int row = cellno / board.length, col = cellno % board.length;
        for (int i = 0; i < dirs.length; i++) 
            int r = dirs[i][0] + row;
            int c = dirs[i][1] + col;
            if (isSafe(board, r, c)&&board[r][c]==-1) 
                int ncell = r * board.length + c;
                board[r][c] = stepno;
                if (knightsTour(board, ncell, stepno + 1)) 
                    return true;
                 else 
                    board[r][c] = -1;
                
            
        


        return false;
    

    private static boolean isSafe(int[][] board, int r, int c) 

        return r >= 0 && c >= 0 && r < board.length && c < board.length;
    

    private static void printBoard(int[][] board) 
        System.out.println(++counter);
        for (int i = 0; i < board.length; i++) 
            for (int j = 0; j < board.length; j++) 
                System.out.print(board[i][j]+" ");

            
            System.out.println();
        
    


【问题讨论】:

该函数不是递归的,也不是迭代的,它不需要任何停止条件。 调试的时候有没有发现什么,一步步去看看它在做什么? 是的,我在进行递归调用之前通过添加打印语句对其进行了调试。工作正常,走步正常,遇到死角后回溯。 【参考方案1】:

您的代码中没有错误,只是蛮力方法很慢,因为搜索空间很大。您可以通过实现Warnsdorf's Rule 来加快搜索速度。这是选择下一步行动的启发式方法,您总是尝试在之后的下一步行动中产生最少可用行动的行动。可以通过几个简单的循环来完成:

int row = cellno / board.length, col = cellno % board.length;

// find move with fewest moves available for the next move:
int minMovesAvailable = 8;
int minMovesDir = 0;
for (int i = 0; i < dirs.length; i++) 
    int r = dirs[i][0] + row;
    int c = dirs[i][1] + col;
    if (isSafe(board, r, c)&&board[r][c]==-1)
    
        board[r][c] = stepno;
        int movesAvailable = 0;
        for (int j = 0; j < dirs.length; j++) 
            int r2 = dirs[j][0] + r;
            int c2 = dirs[j][1] + c;
            if (isSafe(board, r2, c2)&&board[r2][c2]==-1)
            
                movesAvailable++;
            
        
        board[r][c] = -1;
        if(movesAvailable < minMovesAvailable)
        
            minMovesAvailable = movesAvailable;
            minMovesDir = i;
        
    


// now recurse this move first:
// int r = dirs[minMovesDir][0] + row;
// int c = dirs[minMovesDir][1] + col;

【讨论】:

以上是关于Knight's Tour 代码陷入无限循环,无法解决的主要内容,如果未能解决你的问题,请参考以下文章

Knight's Tour C++ 使用堆栈

Knight's tour backtrack 实现选择步长数组

陷入无限循环(骑士之旅问题)

如果依赖项中存在无法解决的冲突,则 Pip 安装会陷入无限循环

尝试使用 Swift 实现无限滚动时陷入无限循环

即使没有进入无限循环,这段代码似乎也永远无法解决