найти кратчайший путь в лабиринте чисел, Java - PullRequest
0 голосов
/ 08 июня 2019

В числовом лабиринте игрок всегда начинает с квадрата в верхнем левом углу и делает определенное количество ходов, которые приведут его / ее к клетке, помеченной как Гол, если решение существует. Значение в каждой ячейке в лабиринте указывает, как далеко игрок должен двигаться горизонтально или вертикально от своей текущей позиции. Моя задача - выяснить, обозначен ли кратчайший путь к ячейке с надписью «Цель», и распечатать его.

Input лабиринт в виде квадратного двумерного массива. Квадрат ворот обозначается цифрой -1 в описании лабиринта. Выход Для лабиринта выведите решение лабиринта или фразу «Решение невозможно». Решения должны быть выведены в виде списка квадратных координат в формате «(строка, столбец)» в порядке их посещения из начать с цели, включая стартовую ячейку. Вам нужно будет сообщить кратчайшее решение от начала до цели. Самое короткое решение будет уникальным. Я попробовал какое-то решение, но я думаю, что есть проблема, решение которой - всегда первый путь, который я нашел, не самый короткий ..

public class findShoretstPath 
{
    private static Stack<Node> stack = new Stack<>();

    private static class Node
    {
        private int[] coordinate = new int[2];
        private int data;
        private Node Right, Left, Top, Bottom;
        public Node(){}
    }

    public static boolean isValid(int[][] a, int x, int y)
    {
       if(x >= 0 && x < a.length && y >= 0 && y < a.length) 
           return true;
       return false;
    }

    public static Node[][] nodeArray(int[][] a)
    {
        Node[][] nodeA = new Node[a.length][a.length];
        for(int i = 0; i<nodeA.length; i++)
            for(int j = 0; j<nodeA[i].length; j++)
            {
                nodeA[i][j] = new Node();
                nodeA[i][j].coordinate[0] = i;
                nodeA[i][j].coordinate[1] = j;
                nodeA[i][j].data = a[i][j];
            }
        for(int i = 0; i<nodeA.length; i++)
            for(int j = 0; j<nodeA[i].length; j++)
            {
                if(isValid(a, i, j+nodeA[i][j].data))
                    nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
                if(isValid(a, i, j-nodeA[i][j].data))
                    nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
                if(isValid(a, i+nodeA[i][j].data, j))
                    nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
                if(isValid(a, i-nodeA[i][j].data, j))
                    nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
            }
        return nodeA;
    }

    public static boolean findPath(Node[][] s, int[][] t, int x, int y)
    {
        boolean b = false;
        if(t[x][y] == 0)
        {
            t[x][y] = 1;
            if(s[x][y].data == -1) b = true;
            else
            {
                if(s[x][y].Right != null) b = findPath(s, t, x, y+s[x][y].data);
                if(!b && s[x][y].Bottom != null) b = findPath(s, t, x+s[x][y].data, y);
                if(!b && s[x][y].Left != null) b = findPath(s, t, x, y-s[x][y].data);
                if(!b && s[x][y].Top != null) b = findPath(s, t, x-s[x][y].data, y);
            }
            if(b) stack.add(s[x][y]);
        }
        return b;
    }

    public static void main(String[] args)
    {
           int[][] maze = {{1,1,1,1,1},
                           {1,1,1,1,1},
                           {1,1,1,1,1},
                           {1,1,1,1,3},
                           {4,1,1,3,-1}};
            Node[][] net = nodeArray(maze);
            int[][] path = new int[maze.length][maze[0].lenght];
            if(findPath(net, path, 0, 0))
            {
                Node temp;
                while(!stack.isEmpty())
                {
                    temp = stack.pop();
                    System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
                }
            }
            else System.out.println("No Solution Possible.");
    }
}

для этого примера вывод должен быть:

(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)

но у меня есть такой вывод:

(0 0) (0 1) (0 2) (0 3) (0 4) (1 4) (2 4) (3 4) (3 1) (3 2) (3 3) (4 3) (4 0) (4 4)

Пожалуйста, помогите как исправить код, чтобы решение было кратчайшим путем?!

1 Ответ

0 голосов
/ 12 июня 2019

После поиска о BFS, теперь я знаю разницу между DFS и BFS. Алгоритм DFS перемещает путь от источника к последнему узлу, если цель найдена остановленной, в противном случае попробуйте другой путь еще раз от источника до последнего узла и так до тех пор, пока цель не будет достигнута. Пока алгоритм BFS перемещается от источника к уровню ниже, если цель найдена, остановитесь, иначе перейдите на следующий уровень и так далее. Для моей проблемы BFS - подходящий алгоритм для поиска кратчайшего пути. Код после некоторых модификаций:

public class findShoretstPath
{
    private static class Node 
    {
        private int[] coordinate = new int[2];
        private int data;
        private Node Right, Left, Top, Bottom;
        public Node(){}
    }


public static boolean isLinked(Node s, Node d) //method to determine if the node d is linked to the node s
{
    if(d.Right == s) return true;
    if(d.Bottom == s) return true;
    if(d.Left == s) return true;
    if(d.Top == s) return true;
    return false;
}

public static boolean isValid(int[][] a, int x, int y)
{
   if(x >= 0 && x < a.length && y >= 0 && y < a.length) 
       return true;
   return false;
}

public static Node[][] nodeArray(int[][] a)
{
    Node[][] nodeA = new Node[a.length][a.length];
    for(int i = 0; i<nodeA.length; i++)
        for(int j = 0; j<nodeA[i].length; j++)
        {
            nodeA[i][j] = new Node();
            nodeA[i][j].coordinate[0] = i;
            nodeA[i][j].coordinate[1] = j;
            nodeA[i][j].data = a[i][j];
        }
    for(int i = 0; i<nodeA.length; i++)
        for(int j = 0; j<nodeA[i].length; j++)
        {
            if(isValid(a, i, j+nodeA[i][j].data))
                nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
            if(isValid(a, i, j-nodeA[i][j].data))
                nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
            if(isValid(a, i+nodeA[i][j].data, j))
                nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
            if(isValid(a, i-nodeA[i][j].data, j))
                nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
        }
    return nodeA;
}

public static void shortestPath(Node[][] nodes, int x, int y)
{
    Stack<Node> stack = new Stack<>();
    Queue<Node> queue = new LinkedList<>();
    int[][] path = new int[nodes.length][nodes[0].length];
    boolean b = false;
    int level = 1;//to keep tracking each level viseted
    queue.add(nodes[x][y]);
    path[x][y] = level;
    while(!queue.isEmpty())
    {
        Node temp;
        level++;
        int size = queue.size();
        for(int i = 0; i<size; i++)
        {
            temp = queue.remove();
            if(temp.data == -1) {b = true; break;}
            if(temp.Right != null && path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] == 0)
            {
                queue.add(temp.Right);
                path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] = level;
            }
            if(temp.Bottom != null && path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] == 0)
            {
                queue.add(temp.Bottom);
                path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] = level;
            }
            if(temp.Left != null && path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] == 0)
            {
                queue.add(temp.Left);
                path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] = level;
            }
            if(temp.Top != null && path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] == 0)
            {
                queue.add(temp.Top);
                path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] = level;
            }
        }
        if(b) break;
    }
    if(b)
    {
        int x1 = 0, y1 = 0;
        for(int i = 0; i<nodes.length; i++)// to locate the position of the goal
            for(int j = 0; j<nodes.length; j++)
                if(nodes[i][j].data == -1)
                {
                    x1 = i; y1 = j;
                }
        stack.add(nodes[x1][y1]);
        int d = path[x1][y1];
        while(d > 0)//go back from the goal to the source
        {
           for(int i = 0; i<path.length; i++)
           {
               if(path[x1][i] == d-1 && isLinked(nodes[x1][y1], nodes[x1][i]))
               {
                  stack.add(nodes[x1][i]);
                  y1 = i;
                  break;
               }
               else if(path[i][y1] == d-1 && isLinked(nodes[x1][y1], nodes[i][y1]))
               {
                  stack.add(nodes[i][y1]);
                  x1 = i;
                  break;
               }
           }
           d--;
        }
        Node temp;
        int stackSize = stack.size();
        for(int i = 0; i<stackSize; i++)// print the final result
        {
           temp = stack.pop();
           System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
        }
    }
    else System.out.print("No Solution Possible.");
}
public static void main(String[] args)
{
       int[][] maze = {{1,1,1,1,1},
                       {1,1,1,1,1},
                       {1,1,1,1,1},
                       {1,1,1,1,3},
                       {4,1,1,3,-1}};
        Node[][] net = nodeArray(maze);
        shortestPath(net, 0, 0));
        System.out.println("");
}
}

и теперь вывод:

(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)
...