We have an n x n grid of 0s and 1s, and we need to find the shortest path from the top-left corner to the bottom-right corner. The path can only go through cells with value 0, and we can move in all 8 directions (up, down, left, right, and the four diagonals). The "length" of the path is the count of cells visited, including both the start and end cells.
Three details shape the solution. First, movement is 8-directional, so from any cell there are up to 8 neighbors to consider, not 4. Second, we want the shortest path, not any path. Third, the path length counts cells, not edges, so a path from (0,0) to (0,0) in a 1x1 grid has length 1.
Every move costs the same (one cell), so the grid is an unweighted graph: each 0-cell is a node, and each adjacent pair of 0-cells shares an edge of weight 1. BFS finds shortest paths in unweighted graphs by exploring level by level, so the first time it reaches the destination it has used the fewest cells possible.
1 <= n <= 100 -> At most 100 x 100 = 10,000 cells. An O(n^2) traversal over all cells is fast, and the heavier O(n^2 log n) variant still finishes well within limits.grid[i][j] is 0 or 1 -> A cell is either passable (0) or blocked (1).BFS processes all cells at distance 1 first, then all cells at distance 2, and so on. The first time it reaches the bottom-right corner, it has used the fewest cells possible, because any shorter path would have arrived in an earlier layer.
The expansion is like a ripple from a stone dropped in water: it grows outward one layer at a time, evenly in all directions. The first layer to touch the destination is the shortest path.
We treat the grid as a graph. Each cell with value 0 is a node. Each pair of adjacent 0-cells (in all 8 directions) is connected by an edge. We start BFS from (0, 0), explore all reachable neighbors, and track the distance. When we reach (n-1, n-1), we return that distance.
BFS processes all nodes at distance d before any node at distance d+1. When it first dequeues the bottom-right cell, no shorter path to it can exist, because such a path would have placed it in an earlier layer.
Marking a cell as visited when it enters the queue, not when it leaves, keeps each cell out of the queue more than once. Several neighbors processed in the same layer can point at the same cell, and the first one to reach it already records the optimal distance, so later attempts would only add duplicate work.
grid[0][0] or the end cell grid[n-1][n-1] is 1. If either is blocked, return -1 immediately.grid[0][0] = 1.BFS explores cells in concentric layers from the start, spending work on cells that lead away from the destination. The next approach directs exploration toward the goal instead.
BFS explores in all directions equally, even though the destination is fixed at the bottom-right corner. A* adds a sense of direction: it prioritizes cells that look closer to the goal, using a heuristic to estimate the remaining distance and processing the most promising cells first.
For a grid with 8-directional movement, the heuristic is the Chebyshev distance (the chessboard distance): max(|row - targetRow|, |col - targetCol|). This is the minimum number of moves a king on a chessboard would need to reach the target. It never overestimates the true remaining distance, which is what keeps A* correct while letting it skip cells BFS would have visited.
The priority of each cell is distance_so_far + heuristic_estimate. Cells that have made the most progress toward the goal are dequeued first.
A* returns the optimal path when its heuristic is admissible (never overestimates the remaining distance). With 8-directional movement and no obstacles, the fewest moves from any cell to the bottom-right corner is exactly max(|row - (n-1)|, |col - (n-1)|). Obstacles can only lengthen a path, so the Chebyshev estimate is always at most the true remaining cost. An admissible heuristic guarantees that the first time the destination is dequeued, its recorded distance is the shortest.
The benefit over BFS is fewer cells expanded, especially in large open grids: A* steers toward the goal instead of radiating outward in every direction.
dist[][] array initialized to infinity. Set dist[0][0] = 1.distance + heuristic. Add (0, 0) with distance 1.dist[row][col], skip it (stale entry).dist + 1 < dist[neighbor], update dist[neighbor] and add it to the priority queue with priority (dist + 1) + chebyshev_distance(neighbor, destination).