📜  安全脱离网格所需的最低限度移动

📅  最后修改于: 2021-04-17 16:15:33             🧑  作者: Mango

给定大小为M * N的网格mat [] [] ,它仅由0 s, 1 s和2 s组成,其中0代表空的地方, 1代表一个人, 2代表火,任务是计算最小值使人员安全离开网格所需的移动次数。在每一步中,火都将燃烧其旁边相邻的牢房,人员将从当前牢房移到其旁边相邻的牢房之一。如果不可能从网格中出来,则打印-1

注意:如果某人到达网格的边界之一,则该人将从网格中出来。

例子:

方法:可以使用概念解决烂橙的问题来解决该问题。这个想法是在蔓延的火势以及人的移动上执行BFS。请按照以下步骤解决问题:

  1. 初始化两个空队列fQpQ ,分别存储火可以蔓延和人员可以移动到的单元。
  2. 初始化一个2D数组,例如Visited [] [] ,以检查人员是否已经访问了单元格(i,j)
  3. 排队人员的所有侧面相邻单元,并将所有相邻单元标记为已访问单元。
  4. 将火力电池的所有相邻边电池放入fQ中,并将所有边相邻的电池标记为燃烧电池。
  5. 初始化一个变量,例如depth ,以跟踪两个像元之间的最短距离。
  6. pQ不为空时,请执行以下步骤:
    • 深度增加1。
    • 将所有单元格从pQ移出,并排入弹出单元格的所有有效侧边相邻单元格。
    • 如果网格的边界处有任何相邻的被排队的像元,则打印depth的值。
    • 否则,将所有单元从fQ出队。对于每个弹出的单元,将所有有效的相邻单元排入队列。
  7. 通过以上步骤,如果无法从网格中出来,请打印-1

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
 
#include 
 
using namespace std;
 
// Stores size of the grid
int m, n;
 
// Function to check valid
// cells of the grid
bool valid(int x, int y)
{
    return (x >= 0 && x < m && y >= 0 && y < n);
}
 
// Checks for the border sides
bool border(int x, int y)
{
    return (x == 0 || x == m - 1 || y == 0 || y == n - 1);
}
 
 
// Function to find shortest distance
// between two cells of the grid
int minStep(vector> mat)
{
 
    // Rows of the grid
    m = mat.size();
 
    // Column of the grid
    n = mat[0].size();
 
    // Stores possible move
    // of the person
    int dx[] = { 1, -1, 0, 0 };
    int dy[] = { 0, 0, 1, -1 };
 
    // Store possible cells visited
    // by the person
    queue > pQ;
 
    // Store possible cells which
    // are burning
    queue > fQ;
 
    // Traverse the grid
    for (int i = 0; i < m; i++){
 
        for (int j = 0; j < n; j++) {
 
            // If current cell is
            // burning
            if (mat[i][j] == 2)
                fQ.push({i, j});
            // If person is in
            // the current cell
            else if (mat[i][j] == 1) {
                if (border(i, j))
                    return 0;
                pQ.push({i, j});
            }
        }
    }
    // Stores shortest distance
    // between two cells
    int depth = 0;
 
    // Check if a cell is visited
    // by the person or not
    vector> visited(n,vector(m,0));
 
    // While pQ is not empty
    while (pQ.size()>0) {
 
        // Update depth
        depth++;
 
        // Popped all the cells from
        // pQ and mark all adjacent cells
        // of as visited
        for (int i = pQ.size(); i > 0;i--) {
 
            // Front element of
            // the queue pQ
            pair  pos = pQ.front();
 
            // Remove front element of
            // the queue pQ
            pQ.pop();
 
            // If cuurent cell is burning
            if (mat[pos.first][pos.second] == 2)
                continue;
 
            // Find all adjacent cells
            for (int j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                int x = pos.first + dx[j];
 
                // Stores column number
                // of adjacent cell
                int y = pos.second + dy[j];
 
                // Checks if current cell
                // is valid
                if (valid(x, y) && mat[x][y] != 2 && !visited[x][y]) {
 
                    // Mark the cell as visited
                    visited[x][y] = 1;
 
                    // Enqueue the cell
                    pQ.push(pair (x, y));
 
                    // Checks the escape condition
                    if (border(x, y))
                        return depth;
                }
            }
        }
 
        // Burn all the adjacent cells
        // of burning cells
        for (int i = fQ.size(); i > 0; i--) {
 
            // Front element of
            // the queue fQ
            pair  pos = fQ.front();
 
            // Delete front element of
            // the queue fQ
            fQ.pop();
 
            // Find adjacent cells of
            // burning cell
            for (int j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                int x = pos.first + dx[j];
 
                // Stores column number
                // of adjacent cell
                int y = pos.second + dy[j];
 
                // Checks if current
                // cell is valid
                if (valid(x, y) && mat[x][y] != 2) {
 
                    mat[x][y] = 2;
 
                    // Burn all the adjacent
                    // cells of current cell
                    fQ.push(pair (x, y));
                }
            }
        }
    }
    return -1;
}
 
// Driver Code
int main()
{
 
    // Given grid
    vector> grid = { { 0, 0, 0, 0 },
                     { 2, 0, 0, 0 },
                     { 2, 1, 0, 0 },
                     { 2, 2, 0, 0 } };
 
    cout<


Java
// Java program to implement
// the above approach
import java.util.*;
import java.lang.*;
class GFG
{
 
    // Structure of cell
    // of the grid
    static class pair
    {
        int x, y;
        pair(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
 
    // Stores size of the grid
    static int m, n;
 
    // Function to find shortest distance
    // between two cells of the grid
    static int minStep(int[][] mat)
    {
 
        // Rows of the grid
        m = mat.length;
 
        // Column of the grid
        n = mat[0].length;
 
        // Stores possible move
        // of the person
        int dx[] = { 1, -1, 0, 0 };
        int dy[] = { 0, 0, 1, -1 };
 
        // Store possible cells visited
        // by the person
        Queue pQ = new LinkedList<>();
 
        // Store possible cells which
        // are burning
        Queue fQ = new LinkedList<>();
 
        // Traverse the grid
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
            {
 
                // If current cell is
                // burning
                if (mat[i][j] == 2)
                    fQ.add(new pair(i, j));
 
                // If person is in
                // the current cell
                else if (mat[i][j] == 1)
                {
                    if (border(i, j))
                        return 0;
                    pQ.add(new pair(i, j));
                }
            }
 
        // Stores shortest distance
        // between two cells
        int depth = 0;
 
        // Check if a cell is visited
        // by the person or not
        boolean[][] visited
            = new boolean[n][m];
 
        // While pQ is not empty
        while (!pQ.isEmpty())
        {
 
            // Update depth
            depth++;
 
            // Popped all the cells from
            // pQ and mark all adjacent cells
            // of as visited
            for (int i = pQ.size(); i > 0; i--)
            {
 
                // Front element of
                // the queue pQ
                pair pos = pQ.peek();
 
                // Remove front element of
                // the queue pQ
                pQ.remove();
 
                // If cuurent cell is burning
                if (mat[pos.x][pos.y] == 2)
                    continue;
 
                // Find all adjacent cells
                for (int j = 0; j < 4; j++)
                {
 
                    // Stores row number of
                    // adjacent cell
                    int x = pos.x + dx[j];
 
                    // Stores column number
                    // of adjacent cell
                    int y = pos.y + dy[j];
 
                    // Checks if current cell
                    // is valid
                    if (valid(x, y) && mat[x][y] != 2
                        && !visited[x][y])
                    {
 
                        // Mark the cell as visited
                        visited[x][y] = true;
 
                        // Enqueue the cell
                        pQ.add(new pair(x, y));
 
                        // Checks the escape condition
                        if (border(x, y))
                            return depth;
                    }
                }
            }
 
            // Burn all the adjacent cells
            // of burning cells
            for (int i = fQ.size(); i > 0; i--)
            {
 
                // Front element of
                // the queue fQ
                pair pos = fQ.peek();
 
                // Delete front element of
                // the queue fQ
                fQ.remove();
 
                // Find adjacent cells of
                // burning cell
                for (int j = 0; j < 4; j++)
                {
 
                    // Stores row number of
                    // adjacent cell
                    int x = pos.x + dx[j];
 
                    // Stores column number
                    // of adjacent cell
                    int y = pos.y + dy[j];
 
                    // Checks if current
                    // cell is valid
                    if (valid(x, y) && mat[x][y] != 2)
                    {
 
                        mat[x][y] = 2;
 
                        // Burn all the adjacent
                        // cells of current cell
                        fQ.add(new pair(x, y));
                    }
                }
            }
        }
        return -1;
    }
 
    // Function to check valid
    // cells of the grid
    static boolean valid(int x, int y)
    {
        return (x >= 0 && x < m
                && y >= 0 && y < n);
    }
 
    // Checks for the border sides
    static boolean border(int x, int y)
    {
        return (x == 0 || x == m - 1
                || y == 0 || y == n - 1);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Given grid
        int[][] grid = { { 0, 0, 0, 0 },
                         { 2, 0, 0, 0 },
                         { 2, 1, 0, 0 },
                         { 2, 2, 0, 0 } };
 
        System.out.println(minStep(grid));
    }
}
 
// This code is contributed by mohit kumar 29.


Python3
# Python3 program to implement
# the above approach
 
# Stores size of the grid
m = 0
n = 0
 
# Function to check valid
# cells of the grid
def valid(x, y):
     
    global n
    global m
    return (x >= 0 and x < m and
            y >= 0 and y < n)
 
# Checks for the border sides
def border(x, y):
     
    global n
    global m
    return (x == 0 or x == m - 1 or
            y == 0 or y == n - 1)
 
# Function to find shortest distance
# between two cells of the grid
def minStep(mat):
     
    global n
    global m
     
    # Rows of the grid
    m = len(mat)
 
    # Column of the grid
    n = len(mat[0])
 
    # Stores possible move
    # of the person
    dx = [1, -1, 0, 0]
    dy = [0, 0, 1, -1]
 
    # Store possible cells visited
    # by the person
    pQ = []
 
    # Store possible cells which
    # are burning
    fQ = []
 
    # Traverse the grid
    for i in range(m):
        for j in range(n):
             
            # If current cell is
            # burning
            if (mat[i][j] == 2):
                fQ.append([i, j])
                 
            # If person is in
            # the current cell
            elif(mat[i][j] == 1):
                if (border(i, j)):
                    return 0
                     
                pQ.append([i, j])
 
    # Stores shortest distance
    # between two cells
    depth = 0
 
    # Check if a cell is visited
    # by the person or not
    visited = [[0 for i in range(m)]
                  for j in range(n)]
 
    # While pQ is not empty
    while (len(pQ) > 0):
         
        # Update depth
        depth += 1
 
        # Popped all the cells from
        # pQ and mark all adjacent cells
        # of as visited
        i = len(pQ)
         
        while(i > 0):
             
            # Front element of
            # the queue pQ
            pos = pQ[0]
 
            # Remove front element of
            # the queue pQ
            pQ.remove(pQ[0])
 
            # If cuurent cell is burning
            if (mat[pos[0]][pos[1]] == 2):
                continue
 
            # Find all adjacent cells
            for j in range(4):
                 
                # Stores row number of
                # adjacent cell
                x = pos[0] + dx[j]
 
                # Stores column number
                # of adjacent cell
                y = pos[1] + dy[j]
 
                # Checks if current cell
                # is valid
                if (valid(x, y) and mat[x][y] != 2 and
                    visited[x][y] == 0):
 
                    # Mark the cell as visited
                    visited[x][y] = 1
 
                    # Enqueue the cell
                    pQ.append([x, y])
 
                    # Checks the escape condition
                    if (border(x, y)):
                        return depth
                         
            i -= 1
 
        # Burn all the adjacent cells
        # of burning cells
        i = len(fQ)
         
        while(i > 0):
 
            # Front element of
            # the queue fQ
            pos = fQ[0]
 
            # Delete front element of
            # the queue fQ
            fQ.remove(fQ[0])
 
            # Find adjacent cells of
            # burning cell
            for j in range(4):
                 
                # Stores row number of
                # adjacent cell
                x = pos[0] + dx[j]
 
                # Stores column number
                # of adjacent cell
                y = pos[1] + dy[j]
 
                # Checks if current
                # cell is valid
                if (valid(x, y) and mat[x][y] != 2):
                    mat[x][y] = 2
 
                    # Burn all the adjacent
                    # cells of current cell
                    fQ.append([x, y])
                     
            i -= 1
 
    return -1
 
# Driver Code
if __name__ == '__main__':
     
    # Given grid
    grid = [ [ 0, 0, 0, 0 ],
             [ 2, 0, 0, 0 ],
             [ 2, 1, 0, 0 ],
             [ 2, 2, 0, 0 ] ]
 
    print(minStep(grid))
 
# This code is contributed by SURENDRA_GANGWAR


C#
// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
public class GFG
{
 
  // Structure of cell
  // of the grid
  class pair
  {
    public int x, y;
    public pair(int x, int y)
    {
      this.x = x;
      this.y = y;
    }
  }
 
  // Stores size of the grid
  static int m, n;
 
  // Function to find shortest distance
  // between two cells of the grid
  static int minStep(int[,] mat)
  {
 
    // Rows of the grid
    m = mat.GetLength(0);
 
    // Column of the grid
    n = mat.GetLength(1);
 
    // Stores possible move
    // of the person
    int []dx = { 1, -1, 0, 0 };
    int []dy = { 0, 0, 1, -1 };
 
    // Store possible cells visited
    // by the person
    Queue pQ = new Queue();
 
    // Store possible cells which
    // are burning
    Queue fQ = new Queue();
 
    // Traverse the grid
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
      {
 
        // If current cell is
        // burning
        if (mat[i, j] == 2)
          fQ.Enqueue(new pair(i, j));
 
        // If person is in
        // the current cell
        else if (mat[i, j] == 1)
        {
          if (border(i, j))
            return 0;
          pQ.Enqueue(new pair(i, j));
        }
      }
 
    // Stores shortest distance
    // between two cells
    int depth = 0;
 
    // Check if a cell is visited
    // by the person or not
    bool[,] visited
      = new bool[n, m];
 
    // While pQ is not empty
    while (pQ.Count != 0)
    {
 
      // Update depth
      depth++;
 
      // Popped all the cells from
      // pQ and mark all adjacent cells
      // of as visited
      for (int i = pQ.Count; i > 0; i--)
      {
 
        // Front element of
        // the queue pQ
        pair pos = pQ.Peek();
 
        // Remove front element of
        // the queue pQ
        pQ.Dequeue();
 
        // If cuurent cell is burning
        if (mat[pos.x, pos.y] == 2)
          continue;
 
        // Find all adjacent cells
        for (int j = 0; j < 4; j++)
        {
 
          // Stores row number of
          // adjacent cell
          int x = pos.x + dx[j];
 
          // Stores column number
          // of adjacent cell
          int y = pos.y + dy[j];
 
          // Checks if current cell
          // is valid
          if (valid(x, y) && mat[x, y] != 2
              && !visited[x, y])
          {
 
            // Mark the cell as visited
            visited[x, y] = true;
 
            // Enqueue the cell
            pQ.Enqueue(new pair(x, y));
 
            // Checks the escape condition
            if (border(x, y))
              return depth;
          }
        }
      }
 
      // Burn all the adjacent cells
      // of burning cells
      for (int i = fQ.Count; i > 0; i--)
      {
 
        // Front element of
        // the queue fQ
        pair pos = fQ.Peek();
 
        // Delete front element of
        // the queue fQ
        fQ.Dequeue();
 
        // Find adjacent cells of
        // burning cell
        for (int j = 0; j < 4; j++)
        {
 
          // Stores row number of
          // adjacent cell
          int x = pos.x + dx[j];
 
          // Stores column number
          // of adjacent cell
          int y = pos.y + dy[j];
 
          // Checks if current
          // cell is valid
          if (valid(x, y) && mat[x, y] != 2)
          {
 
            mat[x, y] = 2;
 
            // Burn all the adjacent
            // cells of current cell
            fQ.Enqueue(new pair(x, y));
          }
        }
      }
    }
    return -1;
  }
 
  // Function to check valid
  // cells of the grid
  static bool valid(int x, int y)
  {
    return (x >= 0 && x < m
            && y >= 0 && y < n);
  }
 
  // Checks for the border sides
  static bool border(int x, int y)
  {
    return (x == 0 || x == m - 1
            || y == 0 || y == n - 1);
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    // Given grid
    int[,] grid = { { 0, 0, 0, 0 },
                   { 2, 0, 0, 0 },
                   { 2, 1, 0, 0 },
                   { 2, 2, 0, 0 } };
 
    Console.WriteLine(minStep(grid));
  }
}
 
// This code is contributed by shikhasingrajput


输出:
2

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