Ruta para llegar a las celdas de borde desde una celda determinada en una cuadrícula 2D sin cruzar celdas especialmente marcadas

Dada una array de dimensiones N*M que consta de los caracteres ‘M’ , ‘#’ , ‘.’ y solo una única instancia de ‘A’ . La tarea es imprimir cualquier ruta desde la celda que tiene el valor A hasta cualquier celda del borde de la array de acuerdo con las siguientes reglas:

  • Cada segundo, la ruta desde la celda ‘A’ puede moverse en las cuatro celdas adyacentes que tienen ‘.’ solo personajes. Los caracteres L , R , U y D representan las direcciones de la celda (X – 1, Y) , (X + 1, Y) , (X, Y – 1) y (X, Y + 1) moviéndose respectivamente de la celda (X, Y) .
  • Las celdas que tienen los caracteres ‘#’ y ‘M’ son las celdas de bloque.
  • Cada segundo, la celda que tiene los caracteres ‘M’ se propaga en las cuatro direcciones del tiempo simultáneamente con el carácter ‘A’ .

Nota: Si no existe tal ruta desde A a ninguna celda del borde de la array, imprima «-1» .

Ejemplos:

Entrada: mat[][] = {{‘#’, ‘M’, ‘.’}, {‘#’, ‘A’, ‘M’}, {‘#’, ‘.’, ‘#’} }
Salida: D
Explicación: 
La array cambia de la siguiente manera:

Por lo tanto, yendo 1 celda hacia abajo, se pueden alcanzar las celdas del borde.

Entrada: mat[][] = {{‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’}, {‘#’, ‘M ‘, ‘.’, ‘.’, ‘SOY’, ‘# ‘, ‘.’, ‘#’}, {‘#’, ‘.’, ‘#’, ‘.’, ‘.’, ‘#’, ‘.’, ‘.’}, {‘5’, ‘#’, ‘.’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’}}
Salida: RRDDR

Enfoque: el problema dado se puede resolver simulando primero el BFS multifuente en la cuadrícula para todas las celdas de bloque ‘M’ y luego realizar BFS desde la celda ‘A’ para verificar si se puede alcanzar o no alguna celda de borde. Siga los pasos a continuación para resolver el problema:

  • Inicialice una array, digamos G[][] que almacena el mínimo para llegar a la celda que tiene valores ‘.’ de todas las celdas que tienen el valor ‘M’ .
  • Realice el BFS multifuente de todas las celdas que tengan valores ‘M’ para encontrar el tiempo mínimo para llegar a cada celda desde su celda más cercana que tenga ‘M’ y guárdela en la array G[][] .
  • Inicialice una array, digamos parent[][] para almacenar el padre de cada celda, digamos (X, Y) cuando se realice cualquier movimiento a la celda (X, Y) .
  • Realice el BFS Traversal en la cuadrícula desde la posición donde aparece ‘A’ , digamos (SX, SY) siguiendo los siguientes pasos:
    • Empuje la celda actual (SX, SY) con la distancia como 0 en la cola .
    • Iterar hasta que la cola no esté vacía y realizar los siguientes pasos:
      • Haga estallar la celda frontal almacenada en la cola .
      • Iterar a través de todas las celdas adyacentes válidas del Node emergente actual y empujar la celda adyacente con el tiempo de descubrimiento incrementado desde la celda emergente en la cola.
      • Actualice el padre de la celda movida desde la celda actual en los pasos anteriores.
      • Si la celda adyacente es la celda del borde, almacene esta celda, digamos (EX, EY) , y salga del bucle .
  • Si no se alcanza el borde de la array, imprima «-1» . De lo contrario, imprima la ruta siguiendo los pasos a continuación:
    • Iterar hasta que la celda final (EX, EY) no sea la misma que la celda inicial (SX, SY) :
      • Encuentre el padre de la celda final y actualice la celda (EX, EY) a su celda principal.
      • Imprima las direcciones L , R , U y D de acuerdo con la diferencia entre la celda final actual y su celda principal.

A continuación se muestra una implementación del enfoque anterior:

C++

// C++ program for tha above approach
#include <bits/stdc++.h>
using namespace std;
  
#define largest 10000000
  
// store the grid (2-d grid)
vector<vector<int> > g;
  
// store the coordinates of the 'M' cells
vector<pair<int, int> > M;
  
// record the parent of a index
vector<vector<pair<pair<int, int>, int> > > parent;
  
// start indices of A
int sx, sy;
  
// For traversing to adjacent cells
int dx[] = { 1, 0, -1, 0 };
int dy[] = { 0, -1, 0, 1 };
  
// rows, columns, end-x, end-y
int n, m, ex = -1, ey = -1;
  
// function to check if the index
// to be processed is valid or not
bool isvalid(int x, int y)
{
    // should not exceed any of the boundary walls
    if (x < 1 || x > n || y < 0 || y > m)
        return false;
  
    // if current cell has '#'
    if (g[x][y] == largest + 1)
        return false;
  
    return true;
}
  
// function to check if the current
// index is at border ornot
bool isborder(int x, int y)
{
    if (x == 1 || y == 1 || x == n || y == m)
        return true;
  
    return false;
}
  
// function to get the direction when
// movement is made from (x --> ex) and (y --> ey)
char cal(int x, int y, int ex, int ey)
{
    if (x + 1 == ex && y == ey)
        return 'D';
  
    if (x - 1 == ex && y == ey)
        return 'U';
  
    if (x == ex && y + 1 == ey)
        return 'R';
  
    return 'L';
}
  
// Function for the multisource
// bfs on M's to store the timers
void fillMatrix()
{
    // queue to store index
    // for bfs and shortest time
    // for each (i, j)
    queue<pair<pair<int, int>, int> > q;
    for (auto m : M) {
  
        // time at this moment is passed as zero
        q.push({ m, 0 });
  
        // insert time 0 for this (x, y)
        g[m.first][m.second] = 0;
    }
  
    // process till the queue becomes empty
    while (!q.empty()) {
  
        // get the index and time of
        // the element at front of queue
        int x = q.front().first.first;
        int y = q.front().first.second;
        int time = q.front().second;
  
        // remove it
        q.pop();
  
        // iterate to all the positions
        // from the given position i.e.
        // (x+1, y), (x-1, y), (x, y+1), (x, y-1)
        for (auto i : { 0, 1, 2, 3 }) {
  
            int newx = x + dx[i];
            int newy = y + dy[i];
  
            // check for validity of current index
            if (!isvalid(newx, newy))
                continue;
  
            // not visited before
            if (g[newx][newy] == -1) {
  
                // update time
                g[newx][newy] = (time + 1);
  
                // push it into the queue
                q.push({ { newx, newy }, time + 1 });
            }
        }
    }
  
    // in the end if there are some places on grid
    // that were blocked and BFS couldn't reach there
    // then just manually iterate over them and
    // change them to largest +1 i.e. treat them as '#'
  
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (g[i][j] == -1) {
                g[i][j] = largest;
            }
        }
    }
}
  
// A's BFS. It will return the time
// when A reaches boundary
// if it is not possible, it will return -1
int bfs()
{
    queue<pair<pair<int, int>, int> > q;
  
    // push the starting (x, y)
    // and it's time as 0
    q.push({ { sx, sy }, 0 });
  
    while (!q.empty()) {
        int x = q.front().first.first;
        int y = q.front().first.second;
        int time = q.front().second;
  
        q.pop();
  
        for (auto i : { 0, 1, 2, 3 }) {
            int newx = x + dx[i];
            int newy = y + dy[i];
  
            if (!isvalid(newx, newy))
                continue;
  
            // Moving to this index is not possible
            if ((time + 1) >= (g[newx][newy]))
                continue;
  
            // index to move on already has
            // a parent i.e. already visited
            if (parent[newx][newy].first.first != -1)
                continue;
  
            // Move to this index and mark the parents
            parent[newx][newy].first.first = x;
            parent[newx][newy].first.second = y;
            parent[newx][newy].second = time + 1;
  
            q.push({ { newx, newy }, time + 1 });
  
            // if this index is a border
            if (isborder(newx, newy)) {
  
                // update ex and ey
                ex = newx;
                ey = newy;
                return time + 1;
            }
        }
    }
  
    // if not possible
    return -1;
}
  
// Function to solve the above problem
void isItPossible(vector<vector<char> > Mat)
{
    // Resize the global vectors
    g.resize(n + 1, vector<int>(m + 1));
    parent.resize(
        n + 1, vector<pair<pair<int, int>, int> >(m + 1));
  
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
  
            // initialize that no one is currently the
            // parent of (i, j)
            parent[i][j].first.first = -1;
            parent[i][j].first.second = -1;
            parent[i][j].second = -1;
  
            char x = Mat[i - 1][j - 1];
            if (x == 'M') {
                // if the input character is 'M',
                // push the coordinates in M and
                // in the grid take 0 as input
                M.push_back({ i, j });
                g[i][j] = 0;
            }
  
            else if (x == 'A') {
                // this is the start x and start y
  
                sx = i, sy = j;
                g[i][j] = -1;
            }
  
            else if (x == '.')
                g[i][j] = -1;
  
            // denote '#' with largest+1
            else
                g[i][j] = largest + 1;
        }
    }
  
    // if already at the border
    if (isborder(sx, sy)) {
        cout << "Already a boundary cell\n";
        return;
    }
  
    // Multisource bfs
    fillMatrix();
  
    // bfs of A
    int time = bfs();
  
    // if (end x) index is -1 and
    // boundary has not been
    if (ex == -1) {
        cout << ex;
    }
    else {
  
        vector<char> ans; // record the path
  
        while (!(ex == sx && ey == sy)) {
            int x = parent[ex][ey].first.first;
            int y = parent[ex][ey].first.second;
  
            // get the direction of movement
            char dir = cal(x, y, ex, ey);
  
            ans.push_back(dir);
            ex = x;
            ey = y;
        }
  
        reverse(ans.begin(), ans.end());
  
        for (auto x : ans) {
            cout << x;
        }
    }
}
// Driver code
int main()
{
    // Input
    vector<vector<char> > Mat = { { '#', 'M', '.' },
                                  { '#', 'A', 'M' },
                                  { '#', '.', '#' } };
    n = Mat.size();
    m = Mat[0].size();
  
    // Function call
    isItPossible(Mat);
    return 0;
}
Producción

D

Tiempo Complejidad: O(n*m)
Espacio Auxiliar: O(n*m)

Publicación traducida automáticamente

Artículo escrito por anirudhpanwar7777 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 *