迷宫中老鼠的变种。
给你一个N * N二维矩阵形状的迷宫(我们称之为 M),左上角的单元格中有一只老鼠,即M[0][0] ,右下角的单元格中有一个逃生门即M[N-1][N-1] 。从每个单元格M[i][j] (0 ≤ i ≤ N-1, 0 ≤ j ≤ N-1) 大鼠可以向右移动多个步骤(例如:到 M[i][j+ s ]),或向下的步数(例如:到 M[i+ s][j]),其中最大步数(或 s 的最大值)可以是单元格M[i][j] 中的值] 。如果任何单元格包含0则这是一个死胡同。例如:在下图中的第二张图片中, M[0][0]处的老鼠可以跳到一个单元格: M[0][1] , M[0][2] , M[1][0] ]或M[2][0] 。
您必须以大小为N * N的矩阵的形式打印从 M[0][0] 到 M[N-1][N-1]的可能路径,以便路径中的单元格具有值1和其他单元格的值为0 。对于上面的例子,一个这样的解决方案是:
这篇文章有针对这个问题的回溯解决方案。
这里介绍了基于动态规划的解决方案。
例子:
Input: mat[][] = {
{3, 0, 0, 2, 1},
{0, 0, 0, 0, 2},
{0, 1, 0, 1, 0},
{1, 0, 0, 1, 1},
{3, 0, 0, 1, 1} }
Output:
1 0 0 1 1
0 0 0 0 1
0 0 0 0 0
0 0 0 0 1
0 0 0 0 1
Input: mat[][] = { {0, 0}, {0, 1} }
Output: No path exists
方法:
- 用false初始化一个布尔CRF[N][N] (可以从)矩阵。现在使CRF[N – 1][N – 1] = true因为可以从目的地到达目的地。
- 现在,从maze[N – 1][N – 1]开始到maze[0][0]结束,根据是否有可能到达任何其他有效单元格更新CRF[][] 中的所有单元格(导致目的地)。
- 当所有CRF[][]矩阵都已更新后,用于创建一个矩阵,该矩阵包含通向目的地的路径中的单元格处全为1且其他单元格为0的矩阵。
- 最后打印这个新创建的矩阵。
- 如果无法到达目的地,则打印No path exists 。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define MAX 50
// Function to check whether the path exists
bool hasPath(int maze[][MAX], int sol[][MAX],
int N)
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sol[i][j] = 0;
// Declaring and initializing CRF
// (can reach from) matrix
bool** CRF = new bool*[N];
for (int i = 0; i < N; i++)
CRF[i] = new bool[N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
CRF[i][j] = false;
CRF[N - 1][N - 1] = true;
// Using the DP to fill CRF matrix
// in correct order
for (int k = N - 1; k >= 0; k--) {
for (int j = k; j >= 0; j--) {
if (!(k == N - 1 && j == N - 1)) {
// If it is possible to get
// to a valid location from
// cell maze[k][j]
for (int a = 0; a <= maze[k][j]; a++) {
if ((j + a < N && CRF[k][j + a] == true)
|| (k + a < N && CRF[k + a][j] == true)) {
CRF[k][j] = true;
break;
}
}
// If it is possible to get to
// a valid location from cell
// maze[j][k]
for (int a = 0; a <= maze[j][k]; a++) {
if ((k + a < N && CRF[j][k + a] == true)
|| (j + a < N && CRF[j + a][k] == true)) {
CRF[j][k] = true;
break;
}
}
}
}
}
// If CRF[0][0] is false it means we cannot reach
// the end of the maze at all
if (CRF[0][0] == false)
return false;
// Filling the solution matrix using CRF
int i = 0, j = 0;
while (!(i == N - 1 && j == N - 1)) {
sol[i][j] = 1;
if (maze[i][j] > 0)
// Get to a valid location from
// the current cell
for (int a = 1; a <= maze[i][j]; a++) {
if ((j + a < N && CRF[i][j + a] == true)) {
j = j + a;
break;
}
else if ((i + a < N && CRF[i + a][j] == true)) {
i = i + a;
break;
}
}
}
sol[N - 1][N - 1] = 1;
return true;
}
// Utility function to print the contents
// of a 2-D array
void printMatrix(int sol[][MAX], int N)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
cout << sol[i][j] << " ";
cout << "\n";
}
}
// Driver code
int main()
{
int maze[][MAX] = { { 2, 2, 1, 1, 0 },
{ 0, 0, 3, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 2, 0, 1 },
{ 0, 0, 3, 0, 0 } };
int N = sizeof(maze) / sizeof(maze[0]);
int sol[N][MAX];
// If path exists
if (hasPath(maze, sol, N))
// Print the path
printMatrix(sol, N);
else
cout << "No path exists";
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static int MAX = 50;
// Function to check whether the path exists
static boolean hasPath(int maze[][],
int sol[][], int N)
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sol[i][j] = 0;
// Declaring and initializing CRF
// (can reach from) matrix
boolean [][]CRF = new boolean[N][N];
CRF[N - 1][N - 1] = true;
// Using the DP to fill CRF matrix
// in correct order
for (int k = N - 1; k >= 0; k--)
{
for (int j = k; j >= 0; j--)
{
if (!(k == N - 1 && j == N - 1))
{
// If it is possible to get
// to a valid location from
// cell maze[k][j]
for (int a = 0; a <= maze[k][j]; a++)
{
if ((j + a < N && CRF[k][j + a] == true) ||
(k + a < N && CRF[k + a][j] == true))
{
CRF[k][j] = true;
break;
}
}
// If it is possible to get to
// a valid location from cell
// maze[j][k]
for (int a = 0; a <= maze[j][k]; a++)
{
if ((k + a < N && CRF[j][k + a] == true) ||
(j + a < N && CRF[j + a][k] == true))
{
CRF[j][k] = true;
break;
}
}
}
}
}
// If CRF[0][0] is false it means we cannot reach
// the end of the maze at all
if (CRF[0][0] == false)
return false;
// Filling the solution matrix using CRF
int i = 0, j = 0;
while (!(i == N - 1 && j == N - 1))
{
sol[i][j] = 1;
if (maze[i][j] > 0)
// Get to a valid location from
// the current cell
for (int a = 1; a <= maze[i][j]; a++)
{
if ((j + a < N && CRF[i][j + a] == true))
{
j = j + a;
break;
}
else if ((i + a < N && CRF[i + a][j] == true))
{
i = i + a;
break;
}
}
}
sol[N - 1][N - 1] = 1;
return true;
}
// Utility function to print the contents
// of a 2-D array
static void printMatrix(int sol[][], int N)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
System.out.print(sol[i][j] + " ");
System.out.println();
}
}
// Driver code
public static void main(String[] args)
{
int maze[][] = {{ 2, 2, 1, 1, 0 },
{ 0, 0, 3, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 2, 0, 1 },
{ 0, 0, 3, 0, 0 }};
int N = maze.length;
int [][]sol = new int [N][MAX];
// If path exists
if (hasPath(maze, sol, N))
// Print the path
printMatrix(sol, N);
else
System.out.println("No path exists");
}
}
// This code is contributed by Princi Singh
C#
// C# implementation of the approach
using System;
class GFG
{
static int MAX = 50;
// Function to check whether the path exists
static Boolean hasPath(int [,]maze,
int [,]sol, int N)
{
int i, j, k;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
sol[i, j] = 0;
// Declaring and initializing CRF
// (can reach from) matrix
Boolean [,]CRF = new Boolean[N, N];
CRF[N - 1, N - 1] = true;
// Using the DP to fill CRF matrix
// in correct order
for (k = N - 1; k >= 0; k--)
{
for (j = k; j >= 0; j--)
{
if (!(k == N - 1 && j == N - 1))
{
// If it is possible to get
// to a valid location from
// cell maze[k,j]
for (int a = 0; a <= maze[k, j]; a++)
{
if ((j + a < N && CRF[k, j + a] == true) ||
(k + a < N && CRF[k + a, j] == true))
{
CRF[k, j] = true;
break;
}
}
// If it is possible to get to
// a valid location from cell
// maze[j,k]
for (int a = 0; a <= maze[j, k]; a++)
{
if ((k + a < N && CRF[j, k + a] == true) ||
(j + a < N && CRF[j + a, k] == true))
{
CRF[j, k] = true;
break;
}
}
}
}
}
// If CRF[0,0] is false it means we cannot
// reach the end of the maze at all
if (CRF[0, 0] == false)
return false;
// Filling the solution matrix using CRF
i = 0; j = 0;
while (!(i == N - 1 && j == N - 1))
{
sol[i, j] = 1;
if (maze[i, j] > 0)
// Get to a valid location from
// the current cell
for (int a = 1; a <= maze[i, j]; a++)
{
if ((j + a < N &&
CRF[i, j + a] == true))
{
j = j + a;
break;
}
else if ((i + a < N &&
CRF[i + a, j] == true))
{
i = i + a;
break;
}
}
}
sol[N - 1, N - 1] = 1;
return true;
}
// Utility function to print the contents
// of a 2-D array
static void printMatrix(int [,]sol, int N)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
Console.Write(sol[i, j] + " ");
Console.WriteLine();
}
}
// Driver code
public static void Main(String[] args)
{
int [,]maze = {{ 2, 2, 1, 1, 0 },
{ 0, 0, 3, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 2, 0, 1 },
{ 0, 0, 3, 0, 0 }};
int N = maze.GetLength(0);
int [,]sol = new int [N, MAX];
// If path exists
if (hasPath(maze, sol, N))
// Print the path
printMatrix(sol, N);
else
Console.WriteLine("No path exists");
}
}
// This code is contributed by Rajput-Ji
Javascript
1 1 1 0 0
0 0 1 0 0
0 0 0 0 0
0 0 1 0 0
0 0 1 0 1
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。