Shortest Path in a Grid (BFS)
Problem
A grid has 0 for open cells and 1 for walls. You start at the top-left cell and want to reach the bottom-right cell. You can move up, down, left or right (not diagonally) through open cells. Print the smallest number of moves, or -1 if there is no path.
Constraints
- 1 <= r, c <= 100
Examples
Input
3 3 0 0 0 1 1 0 0 0 0
Output
4
Solutions
Breadth-first search explores the grid in rings: first all cells at distance 1, then distance 2, and so on. So the first time it reaches a cell, the distance is the shortest one. A queue gives this order.
/*
* Problem : Process a grid.
* Input : r and c, then r rows of c numbers (0 or 1).
* Output : The fewest moves or -1.
* Approach: Breadth-first search.
* Time : O(r * c)
* Space : O(r * c)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method solves the task. It receives the input and returns the answer.
static int solve(int[][] m) {
int rows = m.length;
int cols = m[0].length;
// Step 1: If the start or the end is a wall, there is no path.
if (m[0][0] == 1 || m[rows - 1][cols - 1] == 1) {
return -1;
}
// Step 2: distance[i][j] = moves needed to reach the cell. -1 means: not visited yet.
int[][] distance = new int[rows][cols];
for (int[] row : distance) {
java.util.Arrays.fill(row, -1);
}
// Step 3: A queue keeps the cells to visit. BFS visits cells in the order of their distance.
java.util.ArrayDeque<int[]> queue = new java.util.ArrayDeque<>();
queue.add(new int[] {0, 0});
distance[0][0] = 0;
int[] stepRow = {1, -1, 0, 0};
int[] stepCol = {0, 0, 1, -1};
while (!queue.isEmpty()) {
int[] cell = queue.poll();
// Step 4: The first time we reach the end cell, we have the shortest distance.
if (cell[0] == rows - 1 && cell[1] == cols - 1) {
return distance[cell[0]][cell[1]];
}
// Step 5: Try the four neighbours. Visit open cells that were not visited before.
for (int d = 0; d < 4; d++) {
int nextRow = cell[0] + stepRow[d];
int nextCol = cell[1] + stepCol[d];
if (nextRow >= 0 && nextRow < rows && nextCol >= 0 && nextCol < cols
&& m[nextRow][nextCol] == 0 && distance[nextRow][nextCol] == -1) {
distance[nextRow][nextCol] = distance[cell[0]][cell[1]] + 1;
queue.add(new int[] {nextRow, nextCol});
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int cols = scanner.nextInt();
int[][] m = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m[i][j] = scanner.nextInt();
}
}
System.out.println(solve(m));
}
}
Hints (2)
- Which data structure gives first-in, first-out order?
- Why is the first arrival the shortest?