给定一个维度为N*M的矩阵,由字符‘M’ 、 ‘#’ 、 ‘.’ 组成。并且只有一个‘A’实例。任务是根据以下规则打印从具有值A 的单元格到矩阵的任何边界单元格的任何一条路径:
- 每一秒,来自单元格“A”的路径可以在所有四个带有“.”的相邻单元格中移动。仅字符。字符L 、 R 、 U和D 分别代表单元格(X – 1, Y) 、 (X + 1, Y) 、 (X, Y – 1)和(X, Y + 1)移动的方向来自单元格(X, Y) 。
- 具有字符“#”和“M”的单元格是块单元格。
- 每秒,具有字符‘M’的单元格与字符‘A’同时在所有四个方向上同时传播自身。
注意:如果不存在从A到矩阵的任何边界单元格的任何此类路径,则打印“-1” 。
例子:
Input: mat[][] = {{‘#’, ‘M’, ‘.’}, {‘#’, ‘A’, ‘M’}, {‘#’, ‘.’, ‘#’}}
Output: D
Explanation:
The matrix changes as follows:
Thus, by going 1 cell down, the border cells can be reached.
Input: mat[][] = {{‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’}, {‘#’, ‘M’, ‘.’, ‘.’, ‘A’, ‘.’, ‘.’, ‘#’}, {‘#’, ‘#’, ‘#’, ‘.’, ‘M’, ‘#’, ‘.’, ‘#’}, {‘#’, ‘.’, ‘#’, ‘.’, ‘.’, ‘#’, ‘.’, ‘.’}, {‘5’, ‘#’, ‘.’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’, ‘#’}}
Output: RRDDR
方法:可以通过首先模拟网格上所有块单元‘M’的多源BFS,然后从单元‘A’执行BFS以检查是否可以到达任何边界单元来解决给定的问题。请按照以下步骤解决问题:
- 初始化一个矩阵,比如G[][] ,它存储到达具有值‘.’的单元格的最小值。来自所有具有值‘M’的单元格。
- 从具有值‘M’ 的所有单元格执行多源 BFS 以找到从具有‘M’ 的最近单元格到达每个单元格的最短时间,并将其存储在矩阵G[][] 中。
- 初始化一个矩阵,比如parent[][]来存储每个单元格的父级,比如(X, Y)当对单元格(X, Y)进行任何移动时。
- 从“A”出现的位置开始对网格执行 BFS 遍历,例如(SX, SY)使用以下步骤:
- 将距离为0的当前单元格(SX,SY)推送到队列中。
- 迭代直到队列不为空并执行以下步骤:
- 弹出存储在队列中的前单元格。
- 迭代当前弹出节点的所有有效相邻单元格,并从队列中弹出的单元格中推送具有增加的发现时间的相邻单元格。
- 在上述步骤中从当前单元格更新移动单元格的父级。
- 如果相邻单元格是边界单元格,则存储此单元格,例如(EX, EY) ,并跳出循环。
- 如果未到达矩阵的边界,则打印“-1” 。否则,使用以下步骤打印路径:
- 迭代直到结束单元格(EX, EY)与起始单元格(SX, SY) 不同:
- 找到结束单元格的父单元格并将单元格(EX, EY)更新为其父单元格。
- 根据当前结束单元格与其父单元格之间的差异打印方向L 、 R 、 U和D 。
- 迭代直到结束单元格(EX, EY)与起始单元格(SX, SY) 不同:
下面是上述方法的一个实现:
C++
// C++ program for tha above approach
#include
using namespace std;
#define largest 10000000
// store the grid (2-d grid)
vector > g;
// store the coordinates of the 'M' cells
vector > M;
// record the parent of a index
vector, 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, 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, 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 > Mat)
{
// Resize the global vectors
g.resize(n + 1, vector(m + 1));
parent.resize(
n + 1, vector, 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 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 > Mat = { { '#', 'M', '.' },
{ '#', 'A', 'M' },
{ '#', '.', '#' } };
n = Mat.size();
m = Mat[0].size();
// Function call
isItPossible(Mat);
return 0;
}
D
时间复杂度: O(n*m)
辅助空间: O(n*m)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。