📌  相关文章
📜  在迷宫中找到从角单元到中间单元的路径

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

给定一个包含正数的方形迷宫,找到从角单元(四个极端中的任意一个)到中间单元的所有路径。我们可以从一个单元格向北,向东,向西和向南四个方向精确地移动n步,其中n是该单元格的值

我们可以从单元格mat [i] [j]移到mat [i + n] [j],mat [in] [j],mat [i] [j + n]和mat [i] [jn]其中n是mat [i] [j]的值。

例子

Input:  9 x 9 maze
[ 3, 5, 4, 4, 7, 3, 4, 6, 3 ]
[ 6, 7, 5, 6, 6, 2, 6, 6, 2 ]
[ 3, 3, 4, 3, 2, 5, 4, 7, 2 ]
[ 6, 5, 5, 1, 2, 3, 6, 5, 6 ]
[ 3, 3, 4, 3, 0, 1, 4, 3, 4 ]
[ 3, 5, 4, 3, 2, 2, 3, 3, 5 ]
[ 3, 5, 4, 3, 2, 6, 4, 4, 3 ]
[ 3, 5, 1, 3, 7, 5, 3, 6, 4 ]
[ 6, 2, 4, 3, 4, 5, 4, 5, 1 ]

Output:
(0, 0) -> (0, 3) -> (0, 7) -> 
(6, 7) -> (6, 3) -> (3, 3) -> 
(3, 4) -> (5, 4) -> (5, 2) -> 
(1, 2) -> (1, 7) -> (7, 7) ->
(7, 1) -> (2, 1) -> (2, 4) -> 
(4, 4) -> MID

这个想法是使用回溯。我们从迷宫的每个角单元开始,然后递归检查它是否导致了解。以下是回溯算法–
如果到达目的地

  1. 打印路径

别的

  1. 将当前单元格标记为已访问并将其添加到路径数组。
  2. 沿所有允许的4个方向前进,并递归检查其中是否有任何解决方法。
  3. 如果以上解决方案均无效,则将该单元标记为未访问,并将其从路径数组中删除。

下面是上述方法的实现:

C++
// C++ program to find a path from corner cell to
// middle cell in maze containing positive numbers
#include 
using namespace std;
 
// Rows and columns in given maze
#define N 9
 
// check whether given cell is a valid cell or not.
bool isValid(set > visited,
             pair pt)
{
    // check if cell is not visited yet to
    // avoid cycles (infinite loop) and its
    // row and column number is in range
    return (pt.first >= 0) && (pt.first  < N) &&
           (pt.second >= 0) && (pt.second < N) &&
           (visited.find(pt) == visited.end());
}
 
// Function to print path from source to middle coordinate
void printPath(list > path)
{
    for (auto it = path.begin(); it != path.end(); it++)
        cout << "(" << it->first << ", "
             << it->second << ") -> ";
 
    cout << "MID" << endl << endl;
}
 
// For searching in all 4 direction
int row[] = {-1, 1, 0, 0};
int col[] = { 0, 0, -1, 1};
 
// Cordinates of 4 corners of matrix
int _row[] = { 0, 0, N-1, N-1};
int _col[] = { 0, N-1, 0, N-1};
 
void findPathInMazeUtil(int maze[N][N],
                list > &path,
                set > &visited,
                pair &curr)
{
    // If we have reached the destination cell.
    // print the complete path
    if (curr.first == N / 2 && curr.second == N / 2)
    {
        printPath(path);
        return;
    }
 
    // consider each direction
    for (int i = 0; i < 4; ++i)
    {
        // get value of current cell
        int n = maze[curr.first][curr.second];
 
        // We can move N cells in either of 4 directions
        int x = curr.first + row[i]*n;
        int y = curr.second + col[i]*n;
 
        // Constructs a pair object with its first element
        // set to x and its second element set to y
        pair next = make_pair(x, y);
 
        // if valid pair
        if (isValid(visited, next))
        {
            // mark cell as visited
            visited.insert(next);
 
            // add cell to current path
            path.push_back(next);
 
            // recuse for next cell
            findPathInMazeUtil(maze, path, visited, next);
 
            // backtrack
            path.pop_back();
             
            // remove cell from current path
            visited.erase(next);
        }
    }
}
 
// Function to find a path from corner cell to
// middle cell in maze contaning positive numbers
void findPathInMaze(int maze[N][N])
{
    // list to store complete path
    // from source to destination
    list > path;
 
    // to store cells already visisted in current path
    set > visited;
 
    // Consider each corners as the starting
    // point and search in maze
    for (int i = 0; i < 4; ++i)
    {
        int x = _row[i];
        int y = _col[i];
 
        // Constructs a pair object
        pair pt = make_pair(x, y);
 
        // mark cell as visited
        visited.insert(pt);
 
        // add cell to current path
        path.push_back(pt);
 
        findPathInMazeUtil(maze, path, visited, pt);
 
        // backtrack
        path.pop_back();
 
        // remove cell from current path
        visited.erase(pt);
    }
}
 
int main()
{
    int maze[N][N] =
    {
        { 3, 5, 4, 4, 7, 3, 4, 6, 3 },
        { 6, 7, 5, 6, 6, 2, 6, 6, 2 },
        { 3, 3, 4, 3, 2, 5, 4, 7, 2 },
        { 6, 5, 5, 1, 2, 3, 6, 5, 6 },
        { 3, 3, 4, 3, 0, 1, 4, 3, 4 },
        { 3, 5, 4, 3, 2, 2, 3, 3, 5 },
        { 3, 5, 4, 3, 2, 6, 4, 4, 3 },
        { 3, 5, 1, 3, 7, 5, 3, 6, 4 },
        { 6, 2, 4, 3, 4, 5, 4, 5, 1 }
    };
 
    findPathInMaze(maze);
 
    return 0;
}


Java
// Java program to find a path from corner cell to
// middle cell in maze containing positive numbers
import java.io.*;
 
class GFG {
    public static void main (String[] args) {
 
        // Creating the maze
        int[][] maze = {
            { 3, 5, 4, 4, 7, 3, 4, 6, 3 },
            { 6, 7, 5, 6, 6, 2, 6, 6, 2 },
            { 3, 3, 4, 3, 2, 5, 4, 7, 2 },
            { 6, 5, 5, 1, 2, 3, 6, 5, 6 },
            { 3, 3, 4, 3, 0, 1, 4, 3, 4 },
            { 3, 5, 4, 3, 2, 2, 3, 3, 5 },
            { 3, 5, 4, 3, 2, 6, 4, 4, 3 },
            { 3, 5, 1, 3, 7, 5, 3, 6, 4 },
            { 6, 2, 4, 3, 4, 5, 4, 5, 1 }
        };
         
        // Calling the printPath function
        printPath(maze,0,0,"");
    }
     
    public static void printPath(int[][] maze, int i, int j, String ans){
 
        // If we reach the center cell
        if (i == maze.length/2 && j==maze.length/2){
 
            // Make the final answer, Print the
                // final answer and Return
            ans += "("+i+", "+j+") -> MID";
            System.out.println(ans);
            return;
        }
         
        // If the element at the current position
            // in maze is 0, simply Return as it has
            // been visited before.
        if (maze[i][j]==0){
            return;
        }
         
        // If element is non-zero, then note
            // the element in variable 'k'
        int k = maze[i][j];
         
        // Mark the cell visited by making the
            // element 0. Don't worry, the element
            // is safe in 'k'
        maze[i][j]=0;
         
        // Make recursive calls in all 4
            // directions pro-actively i.e. if the next
            // cell lies in maze or not. Right call
        if (j+k ");
        }
 
        // down call
        if (i+k ");
        }
 
        // left call
        if (j-k>0){
            printPath(maze, i, j-k, ans+"("+i+", "+j+") -> ");
        }
 
        // up call
        if (i-k>0){
            printPath(maze, i-k, j, ans+"("+i+", "+j+") -> ");
        }
         
        // Unmark the visited cell by substituting
            // its original value from 'k'
        maze[i][j] = k;
    }
                         
}


Python3
# Python program to find a path from corner cell to
# middle cell in maze containing positive numbers
def printPath(maze, i, j, ans):
 
    # If we reach the center cell
    if (i == len(maze) // 2 and j == len(maze) // 2):
 
        # Make the final answer, Prthe
        # final answer and Return
        ans += "(" + str(i) + ", " + str(j) + ") -> MID";
        print(ans);
        return;
     
    # If the element at the current position
    # in maze is 0, simply Return as it has
    # been visited before.
    if (maze[i][j] == 0):
        return;
     
    # If element is non-zero, then note
    # the element in variable 'k'
    k = maze[i][j];
 
    # Mark the cell visited by making the
    # element 0. Don't worry, the element
    # is safe in 'k'
    maze[i][j] = 0;
 
    # Make recursive calls in all 4
    # directions pro-actively i.e. if the next
    # cell lies in maze or not. Right call
    if (j + k < len(maze)):
        printPath(maze, i, j + k, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # down call
    if (i + k < len(maze)):
        printPath(maze, i + k, j, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # left call
    if (j - k > 0):
        printPath(maze, i, j - k, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # up call
    if (i - k > 0):
        printPath(maze, i - k, j, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # Unmark the visited cell by substituting
    # its original value from 'k'
    maze[i][j] = k;
 
    # Driver code
if __name__ == '__main__':
 
    # Creating the maze
    maze = [[ 3, 5, 4, 4, 7, 3, 4, 6, 3 ],[ 6, 7, 5, 6, 6, 2, 6, 6, 2 ],[ 3, 3, 4, 3, 2, 5, 4, 7, 2 ],
            [ 6, 5, 5, 1, 2, 3, 6, 5, 6 ],[ 3, 3, 4, 3, 0, 1, 4, 3, 4 ],[ 3, 5, 4, 3, 2, 2, 3, 3, 5 ],
            [ 3, 5, 4, 3, 2, 6, 4, 4, 3 ],[ 3, 5, 1, 3, 7, 5, 3, 6, 4 ],[ 6, 2, 4, 3, 4, 5, 4, 5, 1 ]] ;
 
    # Calling the printPath function
    printPath(maze, 0, 0, "");
 
# This code contributed by gauravrajput1


C#
// C# program to find a path from corner
// cell to middle cell in maze containing
// positive numbers
using System;
 
class GFG{
 
// Driver Code   
public static void Main(String[] args)
{
     
    // Creating the maze
    int[,] maze = {
        { 3, 5, 4, 4, 7, 3, 4, 6, 3 },
        { 6, 7, 5, 6, 6, 2, 6, 6, 2 },
        { 3, 3, 4, 3, 2, 5, 4, 7, 2 },
        { 6, 5, 5, 1, 2, 3, 6, 5, 6 },
        { 3, 3, 4, 3, 0, 1, 4, 3, 4 },
        { 3, 5, 4, 3, 2, 2, 3, 3, 5 },
        { 3, 5, 4, 3, 2, 6, 4, 4, 3 },
        { 3, 5, 1, 3, 7, 5, 3, 6, 4 },
        { 6, 2, 4, 3, 4, 5, 4, 5, 1 }
    };
     
    // Calling the printPath function
    printPath(maze, 0, 0, "");
}
 
public static void printPath(int[,] maze, int i,
                             int j, String ans)
{
     
    // If we reach the center cell
    if (i == maze.GetLength(0) / 2 &&
        j == maze.GetLength(1) / 2)
    {
         
        // Make the readonly answer, Print the
        // readonly answer and Return
        ans += "(" + i + ", " + j + ") -> MID";
        Console.WriteLine(ans);
        return;
    }
     
    // If the element at the current position
    // in maze is 0, simply Return as it has
    // been visited before.
    if (maze[i, j] == 0)
    {
        return;
    }
     
    // If element is non-zero, then note
    // the element in variable 'k'
    int k = maze[i, j];
     
    // Mark the cell visited by making the
    // element 0. Don't worry, the element
    // is safe in 'k'
    maze[i, j] = 0;
     
    // Make recursive calls in all 4
    // directions pro-actively i.e. if the next
    // cell lies in maze or not. Right call
    if (j + k < maze.GetLength(1))
    {
        printPath(maze, i, j + k,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Down call
    if (i + k < maze.GetLength(0))
    {
        printPath(maze, i + k, j,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Left call
    if (j - k > 0)
    {
        printPath(maze, i, j - k,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Up call
    if (i - k > 0)
    {
        printPath(maze, i - k, j,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
     
    // Unmark the visited cell by substituting
    // its original value from 'k'
    maze[i, j] = k;
}
}
 
// This code is contributed by gauravrajput1


输出 :

(0, 0) -> (0, 3) -> (0, 7) -> 
(6, 7) -> (6, 3) -> (3, 3) -> 
(3, 4) -> (5, 4) -> (5, 2) -> 
(1, 2) -> (1, 7) -> (7, 7) ->
(7, 1) -> (2, 1) -> (2, 4) -> 
(4, 4) -> MID

更好的方法:

Java

// Java program to find a path from corner cell to
// middle cell in maze containing positive numbers
import java.io.*;
 
class GFG {
    public static void main (String[] args) {
 
        // Creating the maze
        int[][] maze = {
            { 3, 5, 4, 4, 7, 3, 4, 6, 3 },
            { 6, 7, 5, 6, 6, 2, 6, 6, 2 },
            { 3, 3, 4, 3, 2, 5, 4, 7, 2 },
            { 6, 5, 5, 1, 2, 3, 6, 5, 6 },
            { 3, 3, 4, 3, 0, 1, 4, 3, 4 },
            { 3, 5, 4, 3, 2, 2, 3, 3, 5 },
            { 3, 5, 4, 3, 2, 6, 4, 4, 3 },
            { 3, 5, 1, 3, 7, 5, 3, 6, 4 },
            { 6, 2, 4, 3, 4, 5, 4, 5, 1 }
        };
         
        // Calling the printPath function
        printPath(maze,0,0,"");
    }
     
    public static void printPath(int[][] maze, int i, int j, String ans){
 
        // If we reach the center cell
        if (i == maze.length/2 && j==maze.length/2){
 
            // Make the final answer, Print the
                // final answer and Return
            ans += "("+i+", "+j+") -> MID";
            System.out.println(ans);
            return;
        }
         
        // If the element at the current position
            // in maze is 0, simply Return as it has
            // been visited before.
        if (maze[i][j]==0){
            return;
        }
         
        // If element is non-zero, then note
            // the element in variable 'k'
        int k = maze[i][j];
         
        // Mark the cell visited by making the
            // element 0. Don't worry, the element
            // is safe in 'k'
        maze[i][j]=0;
         
        // Make recursive calls in all 4
            // directions pro-actively i.e. if the next
            // cell lies in maze or not. Right call
        if (j+k ");
        }
 
        // down call
        if (i+k ");
        }
 
        // left call
        if (j-k>0){
            printPath(maze, i, j-k, ans+"("+i+", "+j+") -> ");
        }
 
        // up call
        if (i-k>0){
            printPath(maze, i-k, j, ans+"("+i+", "+j+") -> ");
        }
         
        // Unmark the visited cell by substituting
            // its original value from 'k'
        maze[i][j] = k;
    }
                         
}

Python3

# Python program to find a path from corner cell to
# middle cell in maze containing positive numbers
def printPath(maze, i, j, ans):
 
    # If we reach the center cell
    if (i == len(maze) // 2 and j == len(maze) // 2):
 
        # Make the final answer, Prthe
        # final answer and Return
        ans += "(" + str(i) + ", " + str(j) + ") -> MID";
        print(ans);
        return;
     
    # If the element at the current position
    # in maze is 0, simply Return as it has
    # been visited before.
    if (maze[i][j] == 0):
        return;
     
    # If element is non-zero, then note
    # the element in variable 'k'
    k = maze[i][j];
 
    # Mark the cell visited by making the
    # element 0. Don't worry, the element
    # is safe in 'k'
    maze[i][j] = 0;
 
    # Make recursive calls in all 4
    # directions pro-actively i.e. if the next
    # cell lies in maze or not. Right call
    if (j + k < len(maze)):
        printPath(maze, i, j + k, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # down call
    if (i + k < len(maze)):
        printPath(maze, i + k, j, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # left call
    if (j - k > 0):
        printPath(maze, i, j - k, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # up call
    if (i - k > 0):
        printPath(maze, i - k, j, ans + "(" + str(i) + ", " + str(j) + ") -> ");
     
    # Unmark the visited cell by substituting
    # its original value from 'k'
    maze[i][j] = k;
 
    # Driver code
if __name__ == '__main__':
 
    # Creating the maze
    maze = [[ 3, 5, 4, 4, 7, 3, 4, 6, 3 ],[ 6, 7, 5, 6, 6, 2, 6, 6, 2 ],[ 3, 3, 4, 3, 2, 5, 4, 7, 2 ],
            [ 6, 5, 5, 1, 2, 3, 6, 5, 6 ],[ 3, 3, 4, 3, 0, 1, 4, 3, 4 ],[ 3, 5, 4, 3, 2, 2, 3, 3, 5 ],
            [ 3, 5, 4, 3, 2, 6, 4, 4, 3 ],[ 3, 5, 1, 3, 7, 5, 3, 6, 4 ],[ 6, 2, 4, 3, 4, 5, 4, 5, 1 ]] ;
 
    # Calling the printPath function
    printPath(maze, 0, 0, "");
 
# This code contributed by gauravrajput1

C#

// C# program to find a path from corner
// cell to middle cell in maze containing
// positive numbers
using System;
 
class GFG{
 
// Driver Code   
public static void Main(String[] args)
{
     
    // Creating the maze
    int[,] maze = {
        { 3, 5, 4, 4, 7, 3, 4, 6, 3 },
        { 6, 7, 5, 6, 6, 2, 6, 6, 2 },
        { 3, 3, 4, 3, 2, 5, 4, 7, 2 },
        { 6, 5, 5, 1, 2, 3, 6, 5, 6 },
        { 3, 3, 4, 3, 0, 1, 4, 3, 4 },
        { 3, 5, 4, 3, 2, 2, 3, 3, 5 },
        { 3, 5, 4, 3, 2, 6, 4, 4, 3 },
        { 3, 5, 1, 3, 7, 5, 3, 6, 4 },
        { 6, 2, 4, 3, 4, 5, 4, 5, 1 }
    };
     
    // Calling the printPath function
    printPath(maze, 0, 0, "");
}
 
public static void printPath(int[,] maze, int i,
                             int j, String ans)
{
     
    // If we reach the center cell
    if (i == maze.GetLength(0) / 2 &&
        j == maze.GetLength(1) / 2)
    {
         
        // Make the readonly answer, Print the
        // readonly answer and Return
        ans += "(" + i + ", " + j + ") -> MID";
        Console.WriteLine(ans);
        return;
    }
     
    // If the element at the current position
    // in maze is 0, simply Return as it has
    // been visited before.
    if (maze[i, j] == 0)
    {
        return;
    }
     
    // If element is non-zero, then note
    // the element in variable 'k'
    int k = maze[i, j];
     
    // Mark the cell visited by making the
    // element 0. Don't worry, the element
    // is safe in 'k'
    maze[i, j] = 0;
     
    // Make recursive calls in all 4
    // directions pro-actively i.e. if the next
    // cell lies in maze or not. Right call
    if (j + k < maze.GetLength(1))
    {
        printPath(maze, i, j + k,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Down call
    if (i + k < maze.GetLength(0))
    {
        printPath(maze, i + k, j,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Left call
    if (j - k > 0)
    {
        printPath(maze, i, j - k,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
 
    // Up call
    if (i - k > 0)
    {
        printPath(maze, i - k, j,
                  ans + "(" + i +
                  ", " + j + ") -> ");
    }
     
    // Unmark the visited cell by substituting
    // its original value from 'k'
    maze[i, j] = k;
}
}
 
// This code is contributed by gauravrajput1

输出

(0, 0) -> (0, 3) -> (0, 7) -> 
(6, 7) -> (6, 3) -> (3, 3) ->
(3, 4) -> (5, 4) -> (5, 2) ->
(1, 2) -> (1, 7) -> (7, 7) -> 
(7, 1) -> (2, 1) -> (2, 4) -> 
(4, 4) -> MID