在国际象棋中达到目标的最小数量步数 - 使用BFS进行骑士遍历

时间:2017-12-20 07:50:50

标签: java algorithm search graph-algorithm game-theory

下面给出的代码适用于大小小于13的国际象棋,但在此之后需要花费太多时间并且永远运行。 我想减少到达终点节点的时间。 此代码还找到从starti,startj到endi,endj的最小路径,其中starti和startj的值从1到n-1。

以下是我要解决的问题:
https://www.hackerrank.com/challenges/knightl-on-chessboard/problem

计划:

import java.util.LinkedList;<br>
import java.util.Scanner;

class Node {

    int x,y,dist;

    Node(int x, int y, int dist) {
        this.x = x;
        this.y = y;
        this.dist = dist;
    }

    public String toString() {
        return "x: "+ x +" y: "+y +" dist: "+dist;
    }
}

class Solution {

    public static boolean checkBound(int x, int y, int n) {

        if(x >0 && y>0 && x<=n && y<=n)
            return true;
        return false;
    }

    public static void printAnswer(int answer[][], int n) {
        for(int i=0; i<n-1; i++) {
            for(int j=0; j<n-1; j++) {
                System.out.print(answer[i][j]+" ");
            }
            System.out.println();
        }

    }

    public static int findMinimumStep(int n, int[] start, int[] end, int a, int b) {

        LinkedList<Node> queue = new LinkedList();
        boolean visited[][] = new boolean[n+1][n+1];
        queue.add(new Node(start[0],start[1],0));       
        int x,y;

        int[] dx = new int[] {a, -a, a, -a, b, -b, b, -b};
        int[] dy = new int[] {b, b, -b, -b, a, a, -a, -a};


        while(!queue.isEmpty()) {
            Node z = queue.removeFirst();
            visited[z.x][z.y] = true;

            if(z.x == end[0] && z.y == end[1])
                return z.dist;

            for(int i=0; i<8; i++)
            {
                x = z.x + dx[i];
                y = z.y + dy[i];            
                if(checkBound(x,y,n) && !visited[x][y])
                    queue.add(new Node(x,y,z.dist+1));
            }
        }
        return -1;
    }

    public static void main(String args[]) {

        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int start[] = new int[] {1,1};
        int goal[] = new int[] {n,n};
        int answer[][] = new int[n-1][n-1];

        for(int i=1; i<n; i++) {
            for(int j=i; j<n; j++) {
                int result = findMinimumStep(n, start, goal, i, j);
                answer[i-1][j-1] = result;
                answer[j-1][i-1] = result;
            }
        }
        printAnswer(answer,n);

    }
}

3 个答案:

答案 0 :(得分:2)

您设置visited太晚了,并且将相同的单元格多次添加到队列中,然后您从队列中弹出它们而不检查其访问状态会使事情变得更糟。这导致队列的快速增长。

您需要在将visited添加到队列后立即设置Node

if(checkBound(x,y,n) && !visited[x][y]) {
    queue.add(new Node(x,y,z.dist+1)); 
    visited[x][y] = true;   
}

答案 1 :(得分:0)

即使您优化了代码,也不会降低算法的复杂性。

我认为你需要考虑如何减少搜索空间。或者以巧妙的顺序搜索它。

我会选择A*-search

答案 2 :(得分:0)

您问题中最有效的解决方案是Dijkstra's algorithm。将方块视为节点并将边缘绘制为骑士可以访问的其他方块/节点。然后运行此图的算法。它在对数时间内执行,因此它可以很好地解决大问题。

MrSmith提出的A *搜索建议,是一种启发式方法,因此我不会就此类问题提出建议。

Dijkstra是一个重要的算法,实现它将帮助您在将来解决许多类似的问题,例如您也可以用相同的逻辑解决this problem问题。