📌  相关文章
📜  从源单元格到二进制矩阵的目标单元格通过仅由 1 组成的单元格的最短路径

📅  最后修改于: 2021-09-02 07:33:27             🧑  作者: Mango

给定一个维度为N * M的二进制矩阵mat[][]和分别代表目标单元格的整数对srcdest ,任务是通过单元格找到从给定源单元格到目标单元格的最短移动序列仅由1 s 组成。允许的移动是向左( L )、向右( R )、向上( U ) 和向下( D ) 移动单元格(如果存在)。如果不存在这样的路径,则打印“-1” 。否则,打印移动序列。

例子:

方法:可以通过对给定矩阵从给定源单元格到目标单元格执行 BFS 遍历来解决给定问题。
请按照以下步骤解决给定的问题:

  • 初始化在给定矩阵上执行 BFS 遍历所需的队列。
  • 初始化一个布尔矩阵,比如visited[N][M] ,用于检查给定的单元格是否被访问过。最初,将所有索引设置为false
  • 初始化另一个矩阵,例如distance[N][M] ,用于存储从源节点到每个单元格的最短距离。将其初始化为-1
  • 将字符串pathMoves初始化为“”以存储从目标单元格的路径。
  • 将源节点推入队列,距离为0
  • 迭代直到队列不为空并执行以下步骤:
    • 弹出队列的前端节点,比如currentNode
    • 检查弹出的节点是否是目标节点。如果发现为真,则使用回溯找到从目标单元格到源单元格的路径。
    • 否则,插入当前弹出节点的所有未访问的相邻单元格,距离(previous distance + 1) 。将distance[currentNode.x][currentNode.y]的值更新为(currentDistance + 1)
  • 完成上述步骤后,如果从给定源到目标单元格的路径存在,则打印存储在pathMoves 中的路径作为结果。否则,打印“-1”

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
#define ROW 4
#define COL 4
 
// Stores the coordinates
// of the matrix cell
struct Point {
    int x, y;
};
 
// Stores coordinates of
// a cell and its distance
struct Node {
    Point pt;
    int dist;
};
 
// Check if the given cell is valid or not
bool isValid(int row, int col)
{
    return (row >= 0) && (col >= 0)
           && (row < ROW) && (col < COL);
}
 
// Stores the moves of the directions of adjacent cells
int dRow[] = { -1, 0, 0, 1 };
int dCol[] = { 0, -1, 1, 0 };
 
// Function to find the shortest path from the
// source to destination in the given  matrix
void pathMoves(char mat[][COL],
               Point src, Point dest)
{
    // Stores the distance for each
    // cell from the source cell
    int d[ROW][COL];
    memset(d, -1, sizeof d);
 
    // Distance of source cell is 0
    d[src.x][src.y] = 0;
 
    // Initialize a visited array
    bool visited[ROW][COL];
    memset(visited, false, sizeof visited);
 
    // Mark source cell as visited
    visited[src.x][src.y] = true;
 
    // Create a queue for BFS
    queue q;
 
    // Distance of source cell is 0
    Node s = { src, 0 };
 
    // Enqueue source cell
    q.push(s);
 
    // Keeps track of whether
    // destination is reached or not
    bool ok = false;
 
    // Iterate until queue is not empty
    while (!q.empty()) {
 
        // Deque front of the queue
        Node curr = q.front();
        Point pt = curr.pt;
 
        // If the destination cell is
        // reached, then find the path
        if (pt.x == dest.x
            && pt.y == dest.y) {
 
            int xx = pt.x, yy = pt.y;
            int dist = curr.dist;
 
            // Assign the distance of
            // destination to the
            // distance matrix
            d[pt.x][pt.y] = dist;
 
            // Stores the smallest path
            string pathmoves = "";
 
            // Iterate until source is reached
            while (xx != src.x
                   || yy != src.y) {
 
                // Append D
                if (xx > 0 && d[xx - 1][yy] == dist - 1) {
                    pathmoves += 'D';
                    xx--;
                }
 
                // Append U
                if (xx < ROW - 1
                    && d[xx + 1][yy]
                           == dist - 1) {
                    pathmoves += 'U';
                    xx++;
                }
 
                // Append R
                if (yy > 0 && d[xx][yy - 1] == dist - 1) {
                    pathmoves += 'R';
                    yy--;
                }
 
                // Append L
                if (yy < COL - 1
                    && d[xx][yy + 1]
                           == dist - 1) {
                    pathmoves += 'L';
                    yy++;
                }
                dist--;
            }
 
            // Reverse the backtracked path
            reverse(pathmoves.begin(),
                    pathmoves.end());
 
            cout << pathmoves;
            ok = true;
            break;
        }
 
        // Pop the start of queue
        q.pop();
 
        // Explore all adjacent directions
        for (int i = 0; i < 4; i++) {
            int row = pt.x + dRow[i];
            int col = pt.y + dCol[i];
 
            // If the current cell is valid
            // cell and can be traversed
            if (isValid(row, col)
                && (mat[row][col] == '1'
                    || mat[row][col] == 's'
                    || mat[row][col] == 'd')
                && !visited[row][col]) {
 
                // Mark the adjacent cells as visited
                visited[row][col] = true;
 
                // Enque the adjacent cells
                Node adjCell
                    = { { row, col }, curr.dist + 1 };
                q.push(adjCell);
 
                // Update the distance
                // of the adjacent cells
                d[row][col] = curr.dist + 1;
            }
        }
    }
 
    // If the destination
    // is not reachable
    if (!ok)
        cout << -1;
}
 
// Driver Code
int main()
{
    char mat[ROW][COL] = { { '0', '1', '0', '1' },
                           { '1', '0', '1', '1' },
                           { '0', '1', '1', '1' },
                           { '1', '1', '1', '0' } };
    Point src = { 0, 3 };
    Point dest = { 3, 0 };
 
    pathMoves(mat, src, dest);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
static int ROW;
static int COL;
 
// Stores the coordinates
// of the matrix cell
static class Point
{
    int x, y;
    Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}
 
// Stores coordinates of
// a cell and its distance
static class Node
{
    Point pt;
    int dist;
 
    Node(Point p, int dist)
    {
        this.pt = p;
        this.dist = dist;
    }
}
 
// Check if the given cell is valid or not
static boolean isValid(int row, int col)
{
    return (row >= 0) && (col >= 0) &&
           (row < ROW) && (col < COL);
}
 
// Stores the moves of the directions
// of adjacent cells
static int dRow[] = { -1, 0, 0, 1 };
static int dCol[] = { 0, -1, 1, 0 };
 
// Function to find the shortest path from the
// source to destination in the given  matrix
static void pathMoves(char mat[][], Point src,
                      Point dest)
{
     
    // Stores the distance for each
    // cell from the source cell
    int d[][] = new int[ROW][COL];
    for(int dd[] : d)
        Arrays.fill(dd, -1);
 
    // Distance of source cell is 0
    d[src.x][src.y] = 0;
 
    // Initialize a visited array
    boolean visited[][] = new boolean[ROW][COL];
 
    // Mark source cell as visited
    visited[src.x][src.y] = true;
 
    // Create a queue for BFS
    ArrayDeque q = new ArrayDeque<>();
 
    // Distance of source cell is 0
    Node s = new Node(src, 0);
 
    // Enqueue source cell
    q.addLast(s);
 
    // Keeps track of whether
    // destination is reached or not
    boolean ok = false;
 
    // Iterate until queue is not empty
    while (!q.isEmpty())
    {
         
        // Deque front of the queue
        Node curr = q.removeFirst();
        Point pt = curr.pt;
 
        // If the destination cell is
        // reached, then find the path
        if (pt.x == dest.x && pt.y == dest.y)
        {
            int xx = pt.x, yy = pt.y;
            int dist = curr.dist;
 
            // Assign the distance of
            // destination to the
            // distance matrix
            d[pt.x][pt.y] = dist;
 
            // Stores the smallest path
            String pathmoves = "";
 
            // Iterate until source is reached
            while (xx != src.x || yy != src.y)
            {
                 
                // Append D
                if (xx > 0 &&
                    d[xx - 1][yy] == dist - 1)
                {
                    pathmoves += 'D';
                    xx--;
                }
 
                // Append U
                if (xx < ROW - 1 &&
                    d[xx + 1][yy] == dist - 1)
                {
                    pathmoves += 'U';
                    xx++;
                }
 
                // Append R
                if (yy > 0 &&
                    d[xx][yy - 1] == dist - 1)
                {
                    pathmoves += 'R';
                    yy--;
                }
 
                // Append L
                if (yy < COL - 1 &&
                    d[xx][yy + 1] == dist - 1)
                {
                    pathmoves += 'L';
                    yy++;
                }
                dist--;
            }
 
            // Print reverse the backtracked path
            for(int i = pathmoves.length() - 1;
                    i >= 0; --i)
                System.out.print(pathmoves.charAt(i));
                 
            ok = true;
            break;
        }
 
        // Pop the start of queue
        if (!q.isEmpty())
            q.removeFirst();
 
        // Explore all adjacent directions
        for(int i = 0; i < 4; i++)
        {
            int row = pt.x + dRow[i];
            int col = pt.y + dCol[i];
 
            // If the current cell is valid
            // cell and can be traversed
            if (isValid(row, col) &&
               (mat[row][col] == '1' ||
                mat[row][col] == 's' ||
                mat[row][col] == 'd') &&
                !visited[row][col])
            {
 
                // Mark the adjacent cells as visited
                visited[row][col] = true;
 
                // Enque the adjacent cells
                Node adjCell = new Node(
                    new Point(row, col), curr.dist + 1);
                q.addLast(adjCell);
 
                // Update the distance
                // of the adjacent cells
                d[row][col] = curr.dist + 1;
            }
        }
    }
 
    // If the destination
    // is not reachable
    if (!ok)
        System.out.println(-1);
}
 
// Driver Code
public static void main(String[] args)
{
    char mat[][] = { { '0', '1', '0', '1' },
                     { '1', '0', '1', '1' },
                     { '0', '1', '1', '1' },
                     { '1', '1', '1', '0' } };
 
    ROW = mat.length;
    COL = mat[0].length;
 
    Point src = new Point(0, 3);
    Point dest = new Point(3, 0);
 
    pathMoves(mat, src, dest);
}
}
 
// This code is contributed by Kingash


Python3
# Python3 program for the above approach
from collections import deque
 
# Stores the coordinates
# of the matrix cell
class Point:
    def __init__(self, xx, yy):
        self.x = xx
        self.y = yy
 
# Stores coordinates of
# a cell and its distance
class Node:
    def __init__(self, P, d):
        self.pt = P
        self.dist = d
 
# Check if the given cell is valid or not
def isValid(row, col):
    return (row >= 0) and (col >= 0) and (row < 4) and (col < 4)
 
# Stores the moves of the directions of adjacent cells
dRow = [-1, 0, 0, 1]
dCol = [0, -1, 1, 0]
 
# Function to find the shortest path from the
# source to destination in the given  matrix
def pathMoves(mat, src, dest):
   
    # Stores the distance for each
    # cell from the source cell
    d = [[ -1 for i in range(4)] for i in range(4)]
 
    # Distance of source cell is 0
    d[src.x][src.y] = 0
 
    # Initialize a visited array
    visited = [[ False for i in range(4)] for i in range(4)]
    # memset(visited, false, sizeof visited)
 
    # Mark source cell as visited
    visited[src.x][src.y] = True
 
    # Create a queue for BFS
    q = deque()
 
    # Distance of source cell is 0
    s = Node(src, 0)
 
    # Enqueue source cell
    q.append(s)
 
    # Keeps track of whether
    # destination is reached or not
    ok = False
 
    # Iterate until queue is not empty
    while (len(q)>0):
 
        # Deque front of the queue
        curr = q.popleft()
        pt = curr.pt
 
        # If the destination cell is
        # reached, then find the path
        if (pt.x == dest.x and pt.y == dest.y):
            xx, yy = pt.x, pt.y
            dist = curr.dist
 
            # Assign the distance of
            # destination to the
            # distance matrix
            d[pt.x][pt.y] = dist
 
            # Stores the smallest path
            pathmoves = ""
 
            # Iterate until source is reached
            while (xx != src.x or yy != src.y):
 
                # Append D
                if (xx > 0 and d[xx - 1][yy] == dist - 1):
                    pathmoves += 'D'
                    xx -= 1
 
                # Append U
                if (xx < 4 - 1 and d[xx + 1][yy] == dist - 1):
                    pathmoves += 'U'
                    xx += 1
 
                # Append R
                if (yy > 0 and d[xx][yy - 1] == dist - 1):
                    pathmoves += 'R'
                    yy -= 1
 
                # Append L
                if (yy < 4 - 1 and d[xx][yy + 1] == dist - 1):
                    pathmoves += 'L'
                    yy += 1
                dist -= 1
 
            # Reverse the backtracked path
            pathmoves =  pathmoves[::-1]
 
            print(pathmoves, end = "")
            ok = True
            break
 
        # Pop the start of queue
        # q.pop()
 
        # Explore all adjacent directions
        for i in range(4):
            row = pt.x + dRow[i]
            col = pt.y + dCol[i]
 
            # If the current cell is valid
            # cell and can be traversed
            if (isValid(row, col) and (mat[row][col] == '1' or mat[row][col] == 's' or mat[row][col] == 'd') and (not visited[row][col])):
                
                # Mark the adjacent cells as visited
                visited[row][col] = True
 
                # Enque the adjacent cells
                adjCell = Node( Point(row, col), curr.dist + 1)
                q.append(adjCell)
 
                # Update the distance
                # of the adjacent cells
                d[row][col] = curr.dist + 1
 
    # If the destination
    # is not reachable
    if (not ok):
        print(-1)
 
# Driver Code
if __name__ == '__main__':
    mat =[ ['0', '1', '0', '1'],
          [ '1', '0', '1', '1'],
          [ '0', '1', '1', '1'],
          [ '1', '1', '1', '0']]
 
    src = Point(0, 3)
    dest = Point(3, 0)
 
    pathMoves(mat, src, dest)
 
# This code is contributed by mohit kumar 29.


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
static int ROW;
static int COL;
 
// Stores the coordinates
// of the matrix cell
class Point
{
    public int x, y;
};
 
static Point newPoint(int x, int y)
{
    Point temp = new Point();
    temp.x = x;
    temp.y = y;
    return temp;
}
 
// Stores coordinates of
// a cell and its distance
class Node
{
    public Point pt;
    public int dist;
};
 
static Node newNode(Point p, int dist)
{
    Node temp = new Node();
    temp.pt = p;
    temp.dist = dist;
    return temp;
}
 
// Check if the given cell is valid or not
static bool isValid(int row, int col)
{
    return (row >= 0) && (col >= 0) &&
          (row < ROW) && (col < COL);
}
 
// Stores the moves of the directions
// of adjacent cells
static int []dRow = { -1, 0, 0, 1 };
static int []dCol = { 0, -1, 1, 0 };
 
// Function to find the shortest path from the
// source to destination in the given  matrix
static void pathMoves(char [,]mat, Point src,
                      Point dest)
{
     
    // Stores the distance for each
    // cell from the source cell
    int [,]d = new int[ROW, COL];
    for(int i = 0; i < ROW; i++)
    {
        for(int j = 0; j < COL; j++)
            d[i, j] = -1;
    }
 
    // Distance of source cell is 0
    d[src.x, src.y] = 0;
 
    // Initialize a visited array
    bool [,]visited = new bool[ROW, COL];
 
    // Mark source cell as visited
    visited[src.x, src.y] = true;
 
    // Create a queue for BFS
    Queue q = new Queue();
 
    // Distance of source cell is 0
    Node s = newNode(src, 0);
 
    // Enqueue source cell
    q.Enqueue(s);
 
    // Keeps track of whether
    // destination is reached or not
    bool ok = false;
 
    // Iterate until queue is not empty
    while (q.Count > 0)
    {
         
        // Deque front of the queue
        Node curr = q.Peek();
        q.Dequeue();
        Point pt = curr.pt;
 
        // If the destination cell is
        // reached, then find the path
        if (pt.x == dest.x && pt.y == dest.y)
        {
            int xx = pt.x, yy = pt.y;
            int dist = curr.dist;
 
            // Assign the distance of
            // destination to the
            // distance matrix
            d[pt.x,pt.y] = dist;
 
            // Stores the smallest path
            string pathmoves = "";
 
            // Iterate until source is reached
            while (xx != src.x || yy != src.y)
            {
                 
                // Append D
                if (xx > 0 &&
                  d[xx - 1, yy] == dist - 1)
                {
                    pathmoves += 'D';
                    xx--;
                }
 
                // Append U
                if (xx < ROW - 1 &&
                    d[xx + 1, yy] == dist - 1)
                {
                    pathmoves += 'U';
                    xx++;
                }
 
                // Append R
                if (yy > 0 &&
                    d[xx, yy - 1] == dist - 1)
                {
                    pathmoves += 'R';
                    yy--;
                }
 
                // Append L
                if (yy < COL - 1 &&
                    d[xx, yy + 1] == dist - 1)
                {
                    pathmoves += 'L';
                    yy++;
                }
                dist--;
            }
 
            // Print reverse the backtracked path
            for(int i = pathmoves.Length - 1;
                    i >= 0; --i)
                Console.Write(pathmoves[i]);
                 
            ok = true;
            break;
        }
 
        // Pop the start of queue
        if (q.Count > 0)
        {
            q.Peek();
            q.Dequeue();
        }
 
        // Explore all adjacent directions
        for(int i = 0; i < 4; i++)
        {
            int row = pt.x + dRow[i];
            int col = pt.y + dCol[i];
 
            // If the current cell is valid
            // cell and can be traversed
            if (isValid(row, col) &&
                   (mat[row, col] == '1' ||
                    mat[row, col] == 's' ||
                    mat[row, col] == 'd') &&
               !visited[row, col])
            {
                 
                // Mark the adjacent cells as visited
                visited[row,col] = true;
 
                // Enque the adjacent cells
                Node adjCell = newNode(newPoint(row, col),
                                       curr.dist + 1);
                q.Enqueue(adjCell);
 
                // Update the distance
                // of the adjacent cells
                d[row, col] = curr.dist + 1;
            }
        }
    }
 
    // If the destination
    // is not reachable
    if (ok == false)
        Console.Write(-1);
}
 
// Driver Code
public static void Main()
{
    char [,]mat = { { '0', '1', '0', '1' },
                    { '1', '0', '1', '1' },
                    { '0', '1', '1', '1' },
                    { '1', '1', '1', '0' } };
 
    ROW = mat.GetLength(0);
    COL = mat.GetLength(0);
 
    Point src = newPoint(0, 3);
    Point dest = newPoint(3, 0);
 
    pathMoves(mat, src, dest);
}
}
 
// This code is contributed by SURENDRA_GANGWAR


输出:
DLDLDL

时间复杂度: O(N*M)
辅助空间: O(N*M)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live