簡體   English   中英

騎士巡回賽代碼陷入無限循環,無法解決

[英]Knight's Tour code runs into infinite loop, does not reach a solution

我對“騎士之旅”的遞歸回溯方法遇到了一個無限循環。 起初,我認為問題可能會花很多時間,但是有些解決方案可以立即解決。 請告訴我代碼有什么問題。

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();
        }
    }

}

您的代碼中沒有錯誤,只是蠻力方法很慢,因為搜索空間很大。 您可以通過實施Warnsdorf規則來加快搜索速度。 這是選擇下一個動作的一種試探法,您總是嘗試在該動作之后導致下一個動作的可用動作最少的動作。 可以通過幾個簡單的循環來完成:

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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM