01 BFS
01 BFS
Dijkstra's algorithm works well for finding the shortest path, but our problem has a unique feature: the path costs are either 0 or 1. This is key because any path with only 0-cost edges, no matter how long, will always be better than one that uses even a single 1-cost edge. Therefore, it makes sense to prioritize exploring 0-cost edges first. Only after all 0-cost edges have been explored, should we move on to the 1-cost edges. This insight leads us to a modification of the Breadth-First Search (BFS) algorithm, known as 0-1 BFS.
In 0-1 BFS, we adjust the traditional BFS by using a deque (double-ended queue) instead of a regular queue. The deque allows us to prioritize 0-cost edges more efficiently. Each element of the deque will store the row and column indices of a cell, and we will maintain a minCost grid to track the minimum cost to reach each cell.
1368. Minimum Cost to Make at Least One Valid Path in a Grid
Given an m x n grid. Each cell of the grid has a sign pointing to the next cell you should visit if you are currently in this cell. The sign of grid[i][j] can be:
1which means go to the cell to the right. (i.e go fromgrid[i][j]togrid[i][j + 1])2which means go to the cell to the left. (i.e go fromgrid[i][j]togrid[i][j - 1])3which means go to the lower cell. (i.e go fromgrid[i][j]togrid[i + 1][j])4which means go to the upper cell. (i.e go fromgrid[i][j]togrid[i - 1][j])
Notice that there could be some signs on the cells of the grid that point outside the grid.
You will initially start at the upper left cell (0, 0). A valid path in the grid is a path that starts from the upper left cell (0, 0) and ends at the bottom-right cell (m - 1, n - 1) following the signs on the grid. The valid path does not have to be the shortest.
You can modify the sign on a cell with cost = 1. You can modify the sign on a cell one time only.
Return the minimum cost to make the grid have at least one valid path.
final int[][] dirs = {
{ 0, 1 }, { 0, -1 },
{ 1, 0 }, { -1, 0 } };
public int minCost(int[][] grid) {
int n = grid.length, m = grid[0].length;
// Track minimum cost to reach each cell
int[][] minCost = new int[n][m];
for (int[] row : minCost) {
Arrays.fill(row, Integer.MAX_VALUE);
}
// Use deque for 0-1 BFS - add zero cost moves to front, cost=1 to back
Deque<int[]> deque = new ArrayDeque<>();
deque.offerFirst(new int[] { 0, 0 });
minCost[0][0] = 0;
while (!deque.isEmpty()) {
int[] curr = deque.pollFirst();
int row = curr[0], col = curr[1];
// Try all four directions
for (int dir = 0; dir < 4; dir++) {
int nr = row + dirs[dir][0];
int nc = col + dirs[dir][1];
int cost = (grid[row][col] != (dir + 1)) ? 1 : 0;
// If position is valid and we found a better path
if (nr >= 0 && nr < n &&
nc >= 0 && nc < m &&
minCost[row][col] + cost < minCost[nr][nc]) {
minCost[nr][nc] = minCost[row][col] + cost;
// Add to back if cost=1, front if cost=0
if (cost == 1) {
deque.offerLast(new int[] { nr, nc });
} else {
deque.offerFirst(new int[] { nr, nc });
}
}
}
}
return minCost[n - 1][m - 1];
}