📜  允许在所有可能方向上移动时陷入迷宫问题的老鼠

📅  最后修改于: 2021-05-24 20:41:59             🧑  作者: Mango

考虑将一只老鼠放在n阶方阵m [] []中(0,0)处,并且必须到达(n-1,n-1)的目的地。我们的任务是找到一个排序后的字符串数组,这些字符串表示大鼠在(n-1,n-1)处到达目的地的所有可能方向。老鼠可以移动的方向是“ U”(上),“ D”(下),“ L”(左),“ R”(右)。

例子:

解决方案:
方法:

  1. 从初始索引(即(0,0))开始,并在网格中按向下- >左侧->右侧->向上的顺序查找通过相邻单元格的有效移动(以便获得排序的路径)。
  2. 如果可以移动,则移动到该单元格并存储与move(D,L,R,U)对应的字符,然后再次开始寻找有效的移动,直到最后一个索引(即(n-1,n-1 )) 到达了。
  3. 同样,继续将这些单元格标记为已访问,并且当我们遍历该单元格的所有可能路径时,然后取消标记该单元格的其他不同路径,并从形成的路径中删除字符。
  4. 到达网格的最后一个索引(右下)时,然后存储遍历的路径。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
#define MAX 5
using namespace std;
 
// Function returns true if the
// move taken is valid else
// it will return false.
bool isSafe(int row, int col, int m[][MAX],
                 int n, bool visited[][MAX])
{
    if (row == -1 || row == n || col == -1 ||
                  col == n || visited[row][col]
                           || m[row][col] == 0)
        return false;
 
    return true;
}
 
// Function to print all the possible
// paths from (0, 0) to (n-1, n-1).
void printPathUtil(int row, int col, int m[][MAX],
              int n, string& path, vector&
               possiblePaths, bool visited[][MAX])
{
    // This will check the initial point
    // (i.e. (0, 0)) to start the paths.
    if (row == -1 || row == n || col == -1
               || col == n || visited[row][col]
                           || m[row][col] == 0)
        return;
 
    // If reach the last cell (n-1, n-1)
    // then store the path and return
    if (row == n - 1 && col == n - 1) {
        possiblePaths.push_back(path);
        return;
    }
 
    // Mark the cell as visited
    visited[row][col] = true;
 
    // Try for all the 4 directions (down, left,
    // right, up) in the given order to get the
    // paths in lexicographical order
 
    // Check if downward move is valid
    if (isSafe(row + 1, col, m, n, visited))
    {
        path.push_back('D');
        printPathUtil(row + 1, col, m, n,
                 path, possiblePaths, visited);
        path.pop_back();
    }
 
    // Check if the left move is valid
    if (isSafe(row, col - 1, m, n, visited))
    {
        path.push_back('L');
        printPathUtil(row, col - 1, m, n,
                   path, possiblePaths, visited);
        path.pop_back();
    }
 
    // Check if the right move is valid
    if (isSafe(row, col + 1, m, n, visited))
    {
        path.push_back('R');
        printPathUtil(row, col + 1, m, n,
                   path, possiblePaths, visited);
        path.pop_back();
    }
 
     // Check if the upper move is valid
    if (isSafe(row - 1, col, m, n, visited))
    {
        path.push_back('U');
        printPathUtil(row - 1, col, m, n,
               path, possiblePaths, visited);
        path.pop_back();
    }
 
    // Mark the cell as unvisited for
    // other possible paths
    visited[row][col] = false;
}
 
// Function to store and print
// all the valid paths
void printPath(int m[MAX][MAX], int n)
{
    // vector to store all the possible paths
    vector possiblePaths;
    string path;
    bool visited[n][MAX];
    memset(visited, false, sizeof(visited));
      
    // Call the utility function to
    // find the valid paths
    printPathUtil(0, 0, m, n, path,
                      possiblePaths, visited);
 
    // Print all possible paths
    for (int i = 0; i < possiblePaths.size(); i++)
        cout << possiblePaths[i] << " ";
}
 
// Driver code
int main()
{
    int m[MAX][MAX] = { { 1, 0, 0, 0, 0 },
                        { 1, 1, 1, 1, 1 },
                        { 1, 1, 1, 0, 1 },
                        { 0, 0, 0, 0, 1 },
                        { 0, 0, 0, 0, 1 } };
    int n = sizeof(m) / sizeof(m[0]);
    printPath(m, n);
 
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
 
class GFG{
     
// Vector to store all the possible paths
static Vector possiblePaths = new Vector<>();
static String path = "";
static final int MAX =  5;
 
// Function returns true if the
// move taken is valid else
// it will return false.
static boolean isSafe(int row, int col, int m[][],
                      int n, boolean visited[][])
{
    if (row == -1 || row == n || col == -1 ||
         col == n || visited[row][col] ||
                     m[row][col] == 0)
        return false;
 
    return true;
}
 
// Function to print all the possible
// paths from (0, 0) to (n-1, n-1).
static void printPathUtil(int row, int col, int m[][],
                          int n, boolean visited[][])
{
     
    // This will check the initial point
    // (i.e. (0, 0)) to start the paths.
    if (row == -1 || row == n || col == -1 ||
         col == n || visited[row][col] ||
                     m[row][col] == 0)
        return;
 
    // If reach the last cell (n-1, n-1)
    // then store the path and return
    if (row == n - 1 && col == n - 1)
    {
        possiblePaths.add(path);
        return;
    }
 
    // Mark the cell as visited
    visited[row][col] = true;
 
    // Try for all the 4 directions (down, left,
    // right, up) in the given order to get the
    // paths in lexicographical order
 
    // Check if downward move is valid
    if (isSafe(row + 1, col, m, n, visited))
    {
        path += 'D';
        printPathUtil(row + 1, col, m, n,
                      visited);
        path = path.substring(0, path.length() - 1);
    }
 
    // Check if the left move is valid
    if (isSafe(row, col - 1, m, n, visited))
    {
        path += 'L';
        printPathUtil(row, col - 1, m, n,
                      visited);
        path = path.substring(0, path.length() - 1);
    }
 
    // Check if the right move is valid
    if (isSafe(row, col + 1, m, n, visited))
    {
        path += 'R';
        printPathUtil(row, col + 1, m, n,
                      visited);
        path = path.substring(0, path.length() - 1);
    }
 
    // Check if the upper move is valid
    if (isSafe(row - 1, col, m, n, visited))
    {
        path += 'U';
        printPathUtil(row - 1, col, m, n,
                      visited);
        path = path.substring(0, path.length() - 1);
    }
 
    // Mark the cell as unvisited for
    // other possible paths
    visited[row][col] = false;
}
 
// Function to store and print
// all the valid paths
static void printPath(int m[][], int n)
{
    boolean [][]visited = new boolean[n][MAX];
     
    // Call the utility function to
    // find the valid paths
    printPathUtil(0, 0, m, n, visited);
 
    // Print all possible paths
    for(int i = 0; i < possiblePaths.size(); i++)
        System.out.print(possiblePaths.get(i) + " ");
}
 
// Driver code
public static void main(String[] args)
{
    int m[][] = { { 1, 0, 0, 0, 0 },
                  { 1, 1, 1, 1, 1 },
                  { 1, 1, 1, 0, 1 },
                  { 0, 0, 0, 0, 1 },
                  { 0, 0, 0, 0, 1 } };
    int n = m.length;
     
    printPath(m, n);
}
}
 
// This code is contributed by gauravrajput1


Python3
# Python3 implementation of the above approach
from typing import List
 
MAX = 5
 
# Function returns true if the
# move taken is valid else
# it will return false.
def isSafe(row: int, col: int,
           m: List[List[int]], n: int,
           visited: List[List[bool]]) -> bool:
 
    if (row == -1 or row == n or
        col == -1 or col == n or
        visited[row][col] or m[row][col] == 0):
        return False
 
    return True
 
# Function to print all the possible
# paths from (0, 0) to (n-1, n-1).
def printPathUtil(row: int, col: int,
                  m: List[List[int]],
                  n: int, path: str,
                  possiblePaths: List[str],
                  visited: List[List[bool]]) -> None:
 
    # This will check the initial point
    # (i.e. (0, 0)) to start the paths.
    if (row == -1 or row == n or
        col == -1 or col == n or
        visited[row][col] or m[row][col] == 0):
        return
 
    # If reach the last cell (n-1, n-1)
    # then store the path and return
    if (row == n - 1 and col == n - 1):
        possiblePaths.append(path)
        return
 
    # Mark the cell as visited
    visited[row][col] = True
 
    # Try for all the 4 directions (down, left,
    # right, up) in the given order to get the
    # paths in lexicographical order
 
    # Check if downward move is valid
    if (isSafe(row + 1, col, m, n, visited)):
        path += 'D'
        printPathUtil(row + 1, col, m, n,
                      path, possiblePaths, visited)
        path = path[:-1]
 
    # Check if the left move is valid
    if (isSafe(row, col - 1, m, n, visited)):
        path += 'L'
        printPathUtil(row, col - 1, m, n,
                      path, possiblePaths, visited)
        path = path[:-1]
 
    # Check if the right move is valid
    if (isSafe(row, col + 1, m, n, visited)):
        path += 'R'
        printPathUtil(row, col + 1, m, n,
                      path, possiblePaths, visited)
        path = path[:-1]
 
    # Check if the upper move is valid
    if (isSafe(row - 1, col, m, n, visited)):
        path += 'U'
        printPathUtil(row - 1, col, m, n,
                      path, possiblePaths, visited)
        path = path[:-1]
 
    # Mark the cell as unvisited for
    # other possible paths
    visited[row][col] = False
 
# Function to store and print
# all the valid paths
def printPath(m: List[List[int]], n: int) -> None:
 
    # vector to store all the possible paths
    possiblePaths = []
    path = ""
    visited = [[False for _ in range(MAX)]
                      for _ in range(n)]
                       
    # Call the utility function to
    # find the valid paths
    printPathUtil(0, 0, m, n, path,
                  possiblePaths, visited)
 
    # Print all possible paths
    for i in range(len(possiblePaths)):
        print(possiblePaths[i], end = " ")
 
# Driver code
if __name__ == "__main__":
     
    m = [ [ 1, 0, 0, 0, 0 ],
          [ 1, 1, 1, 1, 1 ],
          [ 1, 1, 1, 0, 1 ],
          [ 0, 0, 0, 0, 1 ],
          [ 0, 0, 0, 0, 1 ] ]
    n = len(m)
     
    printPath(m, n)
 
# This code is contributed by sanjeev2552


C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
class GFG{
     
// List to store all the possible paths
static List possiblePaths = new List();
static String path = "";
static readonly int MAX =  5;
 
// Function returns true if the
// move taken is valid else
// it will return false.
static bool isSafe(int row, int col, int [,]m,
                      int n, bool [,]visited)
{
    if (row == -1 || row == n || col == -1 ||
         col == n || visited[row,col] ||
                     m[row,col] == 0)
        return false;
    return true;
}
 
// Function to print all the possible
// paths from (0, 0) to (n-1, n-1).
static void printPathUtil(int row, int col, int [,]m,
                          int n, bool [,]visited)
{
     
    // This will check the initial point
    // (i.e. (0, 0)) to start the paths.
    if (row == -1 || row == n || col == -1 ||
         col == n || visited[row,col] ||
                     m[row,col] == 0)
        return;
 
    // If reach the last cell (n-1, n-1)
    // then store the path and return
    if (row == n - 1 && col == n - 1)
    {
        possiblePaths.Add(path);
        return;
    }
 
    // Mark the cell as visited
    visited[row,col] = true;
 
    // Try for all the 4 directions (down, left,
    // right, up) in the given order to get the
    // paths in lexicographical order
 
    // Check if downward move is valid
    if (isSafe(row + 1, col, m, n, visited))
    {
        path += 'D';
        printPathUtil(row + 1, col, m, n,
                      visited);
        path = path.Substring(0, path.Length - 1);
    }
 
    // Check if the left move is valid
    if (isSafe(row, col - 1, m, n, visited))
    {
        path += 'L';
        printPathUtil(row, col - 1, m, n,
                      visited);
        path = path.Substring(0, path.Length - 1);
    }
 
    // Check if the right move is valid
    if (isSafe(row, col + 1, m, n, visited))
    {
        path += 'R';
        printPathUtil(row, col + 1, m, n,
                      visited);
        path = path.Substring(0, path.Length - 1);
    }
 
    // Check if the upper move is valid
    if (isSafe(row - 1, col, m, n, visited))
    {
        path += 'U';
        printPathUtil(row - 1, col, m, n,
                      visited);
        path = path.Substring(0, path.Length - 1);
    }
 
    // Mark the cell as unvisited for
    // other possible paths
    visited[row,col] = false;
}
 
// Function to store and print
// all the valid paths
static void printPath(int [,]m, int n)
{
    bool [,]visited = new bool[n,MAX];
     
    // Call the utility function to
    // find the valid paths
    printPathUtil(0, 0, m, n, visited);
 
    // Print all possible paths
    for(int i = 0; i < possiblePaths.Count; i++)
        Console.Write(possiblePaths[i] + " ");
}
 
// Driver code
public static void Main(String[] args)
{
    int [,]m = { { 1, 0, 0, 0, 0 },
                  { 1, 1, 1, 1, 1 },
                  { 1, 1, 1, 0, 1 },
                  { 0, 0, 0, 0, 1 },
                  { 0, 0, 0, 0, 1 } };
    int n = m.GetLength(0);  
    printPath(m, n);
}
}
 
// This code is contributed by gauravrajput1


输出:
DDRRURRDDD DDRURRRDDD DRDRURRDDD DRRRRDDD

复杂度分析:

  • 时间复杂度:O(3 ^(n ^ 2))。
    由于每个单元中有N ^ 2个单元,因此有3个未访问的相邻单元。因此,时间复杂度为O(3 ^(N ^ 2)。
  • 辅助空间: O(3 ^(n ^ 2))。
    由于答案中最多可以有3 ^(n ^ 2)个像元,因此空间复杂度为O(3 ^(n ^ 2))。