Find shortest safe route in a path with landmines in C++

C++Server Side ProgrammingProgramming

In this problem, we are given a matrix mat[][]. It defines a path with landmines which are marked as 0. Our task is to Find shortest safe route in a path with landmines.

While traversing through the safe path, we need to avoid walking adjacent cells of the landmine (left, right, above and bottom) for being unsafe.

All valid moves while traversing the path are −

- Left : mat[i][j] => mat[i-1][j]
- Right : mat[i][j] => mat[i+1][j]
- Top : mat[i][j] => mat[i][j - 1]
- Bottom : mat[i][j] => mat[i][j + 1]

Let’s take an example to understand the problem,

Input

mat[][] = {
   {1, 1, 0, 1},
   {1, 1, 0, 1},
   {1, 1, 1, 1},
   {1, 1, 1, 1}
}

Output

length of shortest safe path is 7

Explanation

{
   {1, 1, 0, 1},
   {1, 1, 0, 1},
   {1, 1, 1, 1},
   {1, 1, 1, 1}
}

Solution Approach

A simple solution to the problem is using backtracking. But before finding the path to the solution, we will mark all the cells that are adjacent to a landmine as unsafe cells. Now, for starting cells in the First column, we will go to each cell that is safe from that position and then check if it leads to a destination (any cell in the last column) or not. Then for all safe positions that can lead to destination, find the shortest path to reach destination. If possible, return length of path

Else return -1, denoting no path found

Program to illustrate the working of our solution,

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
#define R 11
#define C 10
int rowNum[] = { -1, 0, 0, 1 };
int colNum[] = { 0, -1, 1, 0 };
bool isSafe(int mat[R][C], int isvisited[R][C], int x, int y){
   if (mat[x][y] == 0 || isvisited[x][y])
      return false;
   return true;
}
bool isValid(int x, int y){
   if (x < R && y < C && x >= 0 && y >= 0)
      return true;
   return false;
}
void unSafeCellsInPath(int mat[R][C]){
   for (int i = 0; i < R; i++){
      for (int j = 0; j < C; j++){
         if (mat[i][j] == 0){
            for (int k = 0; k < 4; k++)
               if (isValid(i + rowNum[k], j + colNum[k]))
            mat[i + rowNum[k]][j + colNum[k]] = -1;
         }
      }
   }
   for (int i = 0; i < R; i++) {
      for (int j = 0; j < C; j++){
         if (mat[i][j] == -1)
            mat[i][j] = 0;
      }
   }
}
void findShortestSafeRouteRec(int mat[R][C], int isvisited[R][C], int i, int j, int &min_dist, int dist){
   if (j == C-1){
      min_dist = min(dist, min_dist);
      return;
   }
   if (dist > min_dist)
      return;
   isvisited[i][j] = 1;
   for (int k = 0; k < 4; k++){
      if (isValid(i + rowNum[k], j + colNum[k]) && isSafe(mat, isvisited, i + rowNum[k], j + colNum[k])){
         findShortestSafeRouteRec(mat, isvisited, i + rowNum[k], j + colNum[k], min_dist, dist + 1);
      }
   }
   isvisited[i][j] = 0;
}
int findShortestSafeRoute(int mat[R][C]){
   int minSafeDist = INT_MAX;
   int isvisited[R][C];
   unSafeCellsInPath(mat);
   for (int i = 0; i < R; i++) {
      if (mat[i][0] == 1) {
         memset(isvisited, 0, sizeof isvisited);
         findShortestSafeRouteRec(mat, isvisited, i, 0, minSafeDist, 0);
         if(minSafeDist == C - 1)
            break;
      }
   }
   if (minSafeDist != INT_MAX)
      return minSafeDist;
   else
      return -1;
}
int main() {
   int mat[R][C] =
   {
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 },
      { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
      { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 }
   };
   int pathLen = findShortestSafeRoute(mat);
   if(pathLen == -1)
      cout<<"No Safe Path from source to destination possible!";
   else
      cout<<"Shortest Safe route Length is "<<pathLen;
   return 0;
}

Output

Shortest Safe route Length is 10

Alternate solution

An alternate solution to the problem is using breadth first search. Using the queue, we will find the path from first column to last column and then return the minimum distance for the path from first column to last column.

Program to illustrate the working of our solution,

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
#define R 11
#define C 10
int rowNum[] = { -1, 0, 0, 1 };
int colNum[] = { 0, -1, 1, 0 };
struct Key{
   int x,y;
   Key(int i,int j){ x=i;y=j;};
};
bool isValid(int x, int y) {
   if (x < R && y < C && x >= 0 && y >= 0)
      return true;
   return false;
}
int findShortestSafeRoute(int mat[R][C]){
   for (int i = 0; i < R; i++) {
      for (int j = 0; j < C; j++) {
         if (mat[i][j] == 0) {
            for (int k = 0; k < 4; k++)
               if (isValid(i + rowNum[k], j + colNum[k]))
                  mat[i + rowNum[k]][j + colNum[k]] = -1;
         }
      }
   }
   for (int i = 0; i < R; i++) {
      for (int j = 0; j < C; j++) {
         if (mat[i][j] == -1)
            mat[i][j] = 0;
      }
   }
   int visited[R][C];
   for(int i=0;i<R;i++){
      for(int j=0;j<C;j++)
         visited[i][j] = -1;
   }
   queue<Key> distQueue;
   for(int i=0;i<R;i++){
      if(mat[i][0] == 1){
         distQueue.push(Key(i,0));
         visited[i][0] = 0;
      }
   }
   while(!distQueue.empty()){
      Key k = distQueue.front();
      distQueue.pop();
      int d = visited[k.x][k.y];
      int x = k.x;
      int y = k.y;
      for (int k = 0; k < 4; k++) {
         int xp = x + rowNum[k];
         int yp = y + colNum[k];
         if(isValid(xp,yp) && visited[xp][yp] == -1 && mat[xp][yp] == 1){
            visited[xp][yp] = d+1;
            distQueue.push(Key(xp,yp));
         }
      }
   }
   int pathLen = INT_MAX;
   for(int i=0;i<R;i++){
      if(mat[i][C-1] == 1 && visited[i][C-1] != -1){
         pathLen = min(pathLen,visited[i][C-1]);
      }
   }
   if(pathLen == INT_MAX)
      return -1;
   else
      return pathLen;
}
int main() {
   int mat[R][C] =
   {
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 },
      { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
      { 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
      { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 }
   };
   int pathLen = findShortestSafeRoute(mat);
   if(pathLen == -1)
      cout<<"No Safe Path from source to destination possible!";
   else
      cout<<"Shortest Safe route Length is "<<pathLen;
   return 0;
}

Output

Shortest Safe route Length is 10
raja
Published on 16-Mar-2021 06:13:43
Advertisements