📜  迷宫中的老鼠使用堆栈回溯

📅  最后修改于: 2021-05-24 19:00:38             🧑  作者: Mango

先决条件–递归,回溯和堆栈数据结构。

迷宫以块的N * M二进制矩阵形式给出,最初有(0,0)处有老鼠。迷宫[0] [0],老鼠想吃在迷宫中某个给定区域存在的食物(fx,fy)。在迷宫矩阵中,0表示该块是死胡同,而1表示该块可以在从源到目标的路径中使用。老鼠可以沿任何方向(不是对角线)移动到任何块,只要该块不是死胡同即可。

任务是检查是否存在任何路径,以使老鼠可以进食或不进食。不需要打印路径。

例子

Input : maze[4][5] = {
            {1, 0, 1, 1, 0},
            {1, 1, 1, 0, 1},
            {0, 1, 0, 1, 1},
            {1, 1, 1, 1, 1}
        }
        fx = 2, fy=3
Output : Path Found!
The path can be: (0, 0) -> (1, 0) -> (1, 1) -> (2, 1) -> (3, 1) -> (3, 2)  -> (3, 3) -> (2, 3)  

这是许多访谈中都问到的著名的“迷宫中的老鼠”问题,可以使用递归和回溯来解决。我们已经讨论了在迷宫中使用Rat中的递归来解决此问题的回溯解决方案。回溯2。在此讨论了使用堆栈的迭代解决方案。

在上一篇文章中,递归使用调用堆栈来保持存储每个递归调用,然后在函数结束时弹出。我们将通过使用自己的堆栈来执行相同的操作来消除递归。

节点结构用于存储从该节点探索的(i,j)坐标和方向以及下一步尝试的方向。

最初,我们将索引为i = 0,j = 0和dir = 0的节点压入堆栈。我们将以逆时针的方式逐个移动到最顶层节点的所有方向,并且每次尝试新路径时,我们都会将该节点(迷宫块)推入堆栈中。每次都会增加最顶层节点的dir变量,以便每次尝试新的方向时都可以,除非探索了所有方向。 dir = 4。如果dir等于4,我们将从堆栈中弹出该节点,这意味着我们正在退回一步,返回到我们来自的路径。

我们还将维护一个访问矩阵,该矩阵将维护迷宫的哪些块已在路径中使用,或换句话说已在堆栈中使用。在尝试任何方向时,我们还将检查迷宫的障碍物是否不是死胡同,并且也未超出迷宫。

我们将在最上面的节点坐标等于食物的坐标(这意味着我们已经到达食物)或堆栈变空(这意味着没有可能到达食物的路径)的同时执行此操作。

下面是上述方法的实现:

C++
// CPP program to solve Rat in a maze
// problem with backtracking using stack
  
#include 
#include 
#include 
  
using namespace std;
  
#define N 4
#define M 5
  
class node {
public:
    int x, y;
    int dir;
  
    node(int i, int j)
    {
        x = i;
        y = j;
          
        // Initially direction 
        // set to 0
        dir = 0;
    }
};
  
// maze of n*m matrix
int n = N, m = M;
  
// Coordinates of food
int fx, fy;
bool visited[N][M];
  
bool isReachable(int maze[N][M])
{
    // Initially starting at (0, 0).
    int i = 0, j = 0;
      
    stack s;
      
    node temp(i, j);
      
    s.push(temp);
  
    while (!s.empty()) {
  
        // Pop the top node and move to the
        // left, right, top, down or retract 
        // back according the value of node's
        // dir variable.
        temp = s.top();
        int d = temp.dir;
        i = temp.x, j = temp.y;
  
        // Increment the direction and
        // push the node in the stack again.
        temp.dir++;
        s.pop();
        s.push(temp);
  
        // If we reach the Food coordinates
        // return true
        if (i == fx and j == fy) {
            return true;
        }
  
        // Checking the Up direction.
        if (d == 0) {
            if (i - 1 >= 0 and maze[i - 1][j] and 
                                    visited[i - 1][j]) {
                node temp1(i - 1, j);
                visited[i - 1][j] = false;
                s.push(temp1);
            }
        }
  
        // Checking the left direction
        else if (d == 1) {
            if (j - 1 >= 0 and maze[i][j - 1] and 
                                    visited[i][j - 1]) {
                node temp1(i, j - 1);
                visited[i][j - 1] = false;
                s.push(temp1);
            }
        }
  
        // Checking the down direction
        else if (d == 2) {
            if (i + 1 < n and maze[i + 1][j] and 
                                    visited[i + 1][j]) {
                node temp1(i + 1, j);
                visited[i + 1][j] = false;
                s.push(temp1);
            }
        }
        // Checking the right direction
        else if (d == 3) {
            if (j + 1 < m and maze[i][j + 1] and 
                                    visited[i][j + 1]) {
                node temp1(i, j + 1);
                visited[i][j + 1] = false;
                s.push(temp1);
            }
        }
  
        // If none of the direction can take 
        // the rat to the Food, retract back 
        // to the path where the rat came from.
        else {
            visited[temp.x][temp.y] = true;
            s.pop();
        }
    }
  
    // If the stack is empty and
    // no path is found return false.
    return false;
}
  
// Driver code
int main()
{
    // Initially setting the visited
    // array to true (unvisited)
    memset(visited, true, sizeof(visited));
      
    // Maze matrix
    int maze[N][M] = {
        { 1, 0, 1, 1, 0 },
        { 1, 1, 1, 0, 1 },
        { 0, 1, 0, 1, 1 },
        { 1, 1, 1, 1, 1 }
    };
  
    // Food coordinates
    fx = 2;
    fy = 3;
  
    if (isReachable(maze)) {
        cout << "Path Found!" << '\n';
    }
    else
        cout << "No Path Found!" << '\n';
          
    return 0;
}


Java
// Java program to solve Rat in a maze 
// problem with backtracking using stack 
import java.util.Stack;
  
class Node 
{
    private int x, y;
    private int dir;
  
    public Node(int i, int j) 
    {
        this.x = i;
        this.y = j;
          
        // default value for direction set to 0 (Up)
        this.dir = 0; 
    }
  
    public int getX() 
    {
        return x;
    }
  
    public void setX(int x) 
    {
        this.x = x;
    }
  
    public int getY() 
    {
        return y;
    }
  
    public void setY(int y)
    {
        this.y = y;
    }
  
    public int getDir() 
    {
        return dir;
    }
  
    public void setDir(int dir) 
    {
        this.dir = dir;
    }
}
  
public class RatInMaze 
{
    private static final int N = 4;
    private static final int M = 5;
  
    // maze of n*m matrix
    int n = N, m = M;
  
    private static boolean[][] visited = new boolean[N][M];
  
        // Driver code
    public static void main(String[] args) 
    {
        // Initially setting the visited
        // array to true (unvisited)
        setVisited(true);
  
        // Maze matrix
        int maze[][] = {{ 1, 0, 1, 1, 0 }, 
                        { 1, 1, 1, 0, 1 }, 
                        { 0, 1, 0, 1, 1 }, 
                        { 1, 1, 1, 1, 1 } };
  
        if (isReachable(maze)) 
        {
            System.out.println("Path Found!\n");
        }
        else
            System.out.println("No Path Found!\n");
    }
  
    private static void setVisited(boolean b) 
    {
        for (int i = 0; i < visited.length; i++) 
        {
            for (int j = 0; j < visited[i].length; j++)
            {
                visited[i][j] = b;
            }
        }
  
    }
  
    private static boolean isReachable(int maze[][]) 
    {
        // Initially starting at (0, 0).
        int i = 0, j = 0;
          
        // Food coordinates
        // Coordinates of food
        int fx, fy;
        fx = 2;
        fy = 3;
  
        Stack s = new Stack();
  
        Node temp = new Node(i, j);
  
        s.push(temp);
  
        while (!s.empty()) 
        {
  
            // Pop the top node and move to the 
            // left, right, top, down or retract
            // back according the value of node's 
            // dir variable.
            temp = s.peek();
            int d = temp.getDir();
            i = temp.getX();
            j = temp.getY();
  
            // Increment the direction and 
            // push the node in the stack again.
            temp.setDir(temp.getDir() + 1);
            s.pop();
            s.push(temp);
  
            // If we reach the Food coordinates
            // return true
            if (i == fx && j == fy)
            {
                return true;
            }
  
            if (d == 0) 
            { 
                // Checking the Up direction.
                if (i - 1 >= 0 && maze[i - 1][j] == 1 && 
                                        visited[i - 1][j])
                {
                    Node temp1 = new Node(i - 1, j);
                    visited[i - 1][j] = false;
                    s.push(temp1);
                }
            } 
            else if (d == 1) 
            {
                // Checking the left direction
                if (j - 1 >= 0 && maze[i][j - 1] == 1 && 
                                        visited[i][j - 1]) 
                {
                    Node temp1 = new Node(i, j - 1);
                    visited[i][j - 1] = false;
                    s.push(temp1);
                }
            }
            else if (d == 2) 
            { 
                // Checking the down direction
                if (i + 1 < N && maze[i + 1][j] == 1 && 
                                        visited[i + 1][j])
                {
                    Node temp1 = new Node(i + 1, j);
                    visited[i + 1][j] = false;
                    s.push(temp1);
                }
            } 
            else if (d == 3) 
            { 
                // Checking the right direction
                if (j + 1 < M && maze[i][j + 1] == 1 &&
                                        visited[i][j + 1])
                {
                    Node temp1 = new Node(i, j + 1);
                    visited[i][j + 1] = false;
                    s.push(temp1);
                }
            }
  
            // If none of the direction can take 
            // the rat to the Food, retract back
            // to the path where the rat came from.
            else 
            {
                visited[temp.getX()][temp.getY()] = true;
                s.pop();
            }
        }
  
        // If the stack is empty and 
        // no path is found return false.
        return false;
    }
}
  
// This code is contributed by nirajtechi


C#
// C# program to solve Rat in a maze 
// problem with backtracking using stack 
using System;
using System.Collections.Generic;
  
public class Node 
{
    private int x, y;
    private int dir;
  
    public Node(int i, int j) 
    {
        this.x = i;
        this.y = j;
          
        // default value for direction set to 0 (Up)
        this.dir = 0; 
    }
  
    public int getX() 
    {
        return x;
    }
    public void setX(int x) 
    {
        this.x = x;
    }
    public int getY() 
    {
        return y;
    }
    public void setY(int y)
    {
        this.y = y;
    }
    public int getDir() 
    {
        return dir;
    }
    public void setDir(int dir) 
    {
        this.dir = dir;
    }
}
  
public class RatInMaze 
{
    private static readonly int N = 4;
    private static readonly int M = 5;
  
    // maze of n*m matrix
    int n = N, m = M;
  
    private static bool [,]visited = new bool[N,M];
  
        // Driver code
    public static void Main(String[] args) 
    {
        // Initially setting the visited
        // array to true (unvisited)
        setVisited(true);
  
        // Maze matrix
        int [,]maze = {{ 1, 0, 1, 1, 0 }, 
                        { 1, 1, 1, 0, 1 }, 
                        { 0, 1, 0, 1, 1 }, 
                        { 1, 1, 1, 1, 1 } };
  
        if (isReachable(maze)) 
        {
            Console.WriteLine("Path Found!\n");
        }
        else
            Console.WriteLine("No Path Found!\n");
    }
  
    private static void setVisited(bool b) 
    {
        for (int i = 0; i < visited.GetLength(0); i++) 
        {
            for (int j = 0; j < visited.GetLength(0); j++)
            {
                visited[i,j] = b;
            }
        }
  
    }
  
    private static bool isReachable(int [,]maze) 
    {
        // Initially starting at (0, 0).
        int i = 0, j = 0;
          
        // Food coordinates
        // Coordinates of food
        int fx, fy;
        fx = 2;
        fy = 3;
  
        Stack s = new Stack();
  
        Node temp = new Node(i, j);
  
        s.Push(temp);
  
        while (s.Count!=0) 
        {
  
            // Pop the top node and move to the 
            // left, right, top, down or retract
            // back according the value of node's 
            // dir variable.
            temp = s.Peek();
            int d = temp.getDir();
            i = temp.getX();
            j = temp.getY();
  
            // Increment the direction and 
            // push the node in the stack again.
            temp.setDir(temp.getDir() + 1);
            s.Pop();
            s.Push(temp);
  
            // If we reach the Food coordinates
            // return true
            if (i == fx && j == fy)
            {
                return true;
            }
  
            if (d == 0) 
            { 
                // Checking the Up direction.
                if (i - 1 >= 0 && maze[i - 1,j] == 1 && 
                                        visited[i - 1,j])
                {
                    Node temp1 = new Node(i - 1, j);
                    visited[i - 1,j] = false;
                    s.Push(temp1);
                }
            } 
            else if (d == 1) 
            {
                // Checking the left direction
                if (j - 1 >= 0 && maze[i,j - 1] == 1 && 
                                        visited[i,j - 1]) 
                {
                    Node temp1 = new Node(i, j - 1);
                    visited[i,j - 1] = false;
                    s.Push(temp1);
                }
            }
            else if (d == 2) 
            { 
                // Checking the down direction
                if (i + 1 < N && maze[i + 1,j] == 1 && 
                                        visited[i + 1,j])
                {
                    Node temp1 = new Node(i + 1, j);
                    visited[i + 1,j] = false;
                    s.Push(temp1);
                }
            } 
            else if (d == 3) 
            { 
                // Checking the right direction
                if (j + 1 < M && maze[i,j + 1] == 1 &&
                                        visited[i,j + 1])
                {
                    Node temp1 = new Node(i, j + 1);
                    visited[i,j + 1] = false;
                    s.Push(temp1);
                }
            }
  
            // If none of the direction can take 
            // the rat to the Food, retract back
            // to the path where the rat came from.
            else
            {
                visited[temp.getX(),temp.getY()] = true;
                s.Pop();
            }
        }
  
        // If the stack is empty and 
        // no path is found return false.
        return false;
    }
}
  
// This code contributed by Rajput-Ji


输出:
Path Found!

注意:我们也可以通过仅将节点弹出堆栈来打印路径,然后以相反的顺序打印它们。

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。