Rata en un laberinto | Retroceder usando Stack

Requisitos previos : recursividad , retroceso y estructura de datos de pila .
Un Laberinto se da como array binaria N*M de bloques y hay una rata inicialmente en (0, 0), es decir. maze[0][0] y la rata quiere comer comida que está presente en algún bloque dado en el laberinto (fx, fy). En una array de laberinto, 0 significa que el bloque es un callejón sin salida y 1 significa que el bloque se puede utilizar en la ruta desde el origen hasta el destino. La rata puede moverse en cualquier dirección (no en diagonal) hacia cualquier bloque siempre que el bloque no sea un callejón sin salida. 
La tarea es comprobar si existe algún camino para que la rata pueda llegar a la comida o no. No es necesario imprimir la ruta.
Ejemplos
 

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)  

Este es el famoso problema de la Rata en un Laberinto planteado en muchas entrevistas que se puede resolver usando Recursion y Backtracking. Ya hemos discutido una solución de Backtracking para este problema usando recursividad en Rat in a Maze | Retroceso-2 . En esto se discute una solución iterativa usando stack.
En el artículo anterior , Recursion usa una pila de llamadas para mantener en el almacén cada llamada recursiva y luego aparecer cuando finaliza la función. Eliminaremos la recursividad usando nuestra propia pila para hacer lo mismo.
Se utiliza una estructura de Node para almacenar las coordenadas (i, j) y las direcciones exploradas desde este Node y qué dirección probar a continuación. 
 

Estructura utilizada: 
 

  1. X : coordenada x del Node 
     
  2. Y : coordenada y del Node 
     
  3. dir : esta variable se usará para decir qué direcciones hemos probado y cuál elegir a continuación. Probaremos todas las direcciones en sentido contrario a las agujas del reloj empezando por Arriba. Inicialmente se le asignará 0. 
    • Si dir=0 prueba la dirección hacia arriba.
    • Si dir=1 intente dirección izquierda.
    • Si dir=2 prueba la dirección hacia abajo.
    • Si dir=3 intente en la dirección correcta.

 

Inicialmente, empujaremos un Node con índices i=0, j=0 y dir=0 en la pila. Nos moveremos en todas las direcciones del Node superior uno por uno en sentido contrario a las agujas del reloj y cada vez que intentemos un nuevo camino empujaremos ese Node (bloque del laberinto) en la pila. Aumentaremos la variable dir del Node superior cada vez para que podamos probar una nueva dirección cada vez a menos que se exploren todas las direcciones, es decir. dirección=4. Si dir es igual a 4, sacaremos ese Node de la pila, lo que significa que estamos retrocediendo un paso hacia el camino de donde vinimos.
También mantendremos una array visitada que mantendrá qué bloques del laberinto ya se usan en el camino o, en otras palabras, están presentes en la pila. Mientras probamos cualquier dirección, también verificaremos si el bloque del laberinto no es un callejón sin salida y tampoco está fuera del laberinto.
Haremos esto mientras las coordenadas del Node superior se vuelven iguales a las coordenadas de la comida, lo que significa que hemos llegado a la comida o la pila se vacía, lo que significa que no hay un camino posible para llegar a la comida.
A continuación se muestra la implementación del enfoque anterior: 
 

C++

// CPP program to solve Rat in a maze
// problem with backtracking using stack
 
#include <cstring>
#include <iostream>
#include <stack>
 
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<node> 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<Node> s = new Stack<Node>();
 
        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<Node> s = new Stack<Node>();
 
        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

Python3

# Python3 program to solve Rat in a maze
# problem with backtracking using stack
 
N=4
M=5
 
class node:
    def __init__(self,i,j):
        self.x=i
        self.y=j
        self.dirn=0
 
# maze of n*m matrix
n = N; m = M
 
# Coordinates of food
fx=0; fy=0
visited=[[True]*N for _ in range(M)]
 
def isReachable(maze):
 
    # Initially starting at (0, 0).
    i = 0; j = 0
     
    s=[]
     
    temp=node(i, j)
     
    s.append(temp)
 
    while s:
 
        # Pop the top node and move to the
        # left, right, top, down or retract
        # back according the value of node's
        # dirn variable.
        temp = s.pop()
        d = temp.dirn
        i = temp.x; j = temp.y
 
        # Increment the direction and
        # push the node in the stack again.
        temp.dirn+=1
        s.append(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]):
                temp1=node(i - 1, j)
                visited[i - 1][j] = False
                s.append(temp1)
             
 
        # Checking the left direction
        elif (d == 1):
            if(j - 1 >= 0 and maze[i][j - 1] and visited[i][j - 1]):
                temp1=node(i, j - 1)
                visited[i][j - 1] = False
                s.append(temp1)
 
 
        # Checking the down direction
        elif (d == 2):
            if(i + 1 < n and maze[i + 1][j] and visited[i + 1][j]):
                temp1=node(i + 1, j)
                visited[i + 1][j] = False
                s.append(temp1)
             
         
        # Checking the right direction
        elif (d == 3):
            if (j + 1 < m and maze[i][j + 1] and visited[i][j + 1]):
                temp1=node(i, j + 1)
                visited[i][j + 1] = False
                s.append(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
if __name__ == '__main__':
 
    # Initially setting the visited
    # array to true (unvisited)
     
    # Maze matrix
    maze = [
        [ 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)):
        print("Path Found!")
    else:
        print("No Path Found!")

Javascript

<script>
 
// JavaScript program to solve Rat in a maze
// problem with backtracking using stack
 
const N = 4
const M = 5
 
class node{
    constructor(i, j){
        this.x = i
        this.y = j
        this.dirn = 0
   }
}
 
// maze of n*m matrix
let n = N, m = M
 
// Coordinates of food
let fx = 0, fy = 0
let visited = new Array(N);
for(let i = 0; i < N; i++){
   visited[i] = new Array(M).fill(true);
}
 
function isReachable(maze){
 
    // Initially starting at (0, 0).
    let i = 0, j = 0
    let s=[]
    let temp=new node(i, j)
    s.push(temp)
 
    while(s.length>0){
 
        // Pop the top node && move to the
        // left, right, top, down or retract
        // back according the value of node's
        // dirn variable.
        temp = s[s.length - 1]
      s.pop()
        let d = temp.dirn
        i = temp.x, j = temp.y
 
        // Increment the direction &&
        // push the node in the stack again.
        temp.dirn+=1
        s.push(temp)
 
        // If we reach the Food coordinates
        // return true
        if (i == fx && j == fy)
            return true
 
 
        // Checking the Up direction.
        if (d == 0){
            if (i - 1 >= 0 && maze[i - 1][j] && visited[i - 1][j]){
                let temp1=new node(i - 1, j)
                visited[i - 1][j] = false
                s.push(temp1)
         }
      }
             
        // Checking the left direction
        else if (d == 1){
            if(j - 1 >= 0 && maze[i][j - 1] && visited[i][j - 1]){
                let temp1=new node(i, j - 1)
                visited[i][j - 1] = false
                s.push(temp1)
         }
      }
 
        // Checking the down direction
        else if (d == 2){
            if(i + 1 < n && maze[i + 1][j] && visited[i + 1][j]){
                let temp1=new node(i + 1, j)
                visited[i + 1][j] = false
                s.push(temp1)
         }
      }
             
        // Checking the right direction
        else if (d == 3){
            if (j + 1 < m && maze[i][j + 1] && visited[i][j + 1]){
                let 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.x][temp.y] = true
            s.pop()
      }
   }
 
    // If the stack is empty &&
    // no path is found return false.
    return false
}
 
// Driver code
 
// Initially setting the visited
// array to true (unvisited)
 
// Maze matrix
let maze = [
        [ 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))
    document.write("Path Found!","</br>")
else
    document.write("No Path Found!","</br>")
 
// This code is contributed by shinjanpatra
 
</script>
Producción: 

Path Found!

 

Nota: También podemos imprimir la ruta simplemente sacando los Nodes de las pilas y luego imprimiéndolos en orden inverso.
Complejidad de Tiempo : O( 2 ^ {N * M}    ).
Espacio Auxiliar: O( NUEVO MÉJICO    ). 

Publicación traducida automáticamente

Artículo escrito por imdhruvgupta y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *