BFS中每个点只入列一次,但有时,我们可能需要bfs中允许一个点入列多次才能解决问题,这种方法就是SPFA。
class Solution {
public int minCost(int[][] grid) {
int m = grid.length, n = grid[0].length;
boolean[][] vis = new boolean[m][n];
int[][] dis = new int[m][n];
int[] dx = { 0, 0, 0, 1, -1 };
int[] dy = { 0, 1, -1, 0, 0 };
// 初始化dis
for (int[] d : dis)
Arrays.fill(d, Integer.MAX_VALUE);
Queue<Point> qu = new LinkedList<>();
vis[0][0] = true;
dis[0][0] = 0;
qu.offer(new Point(0, 0));
while (!qu.isEmpty()) {
Point curPoint = qu.poll();
int curx = curPoint.x;
int cury = curPoint.y;
vis[curx][cury] = false;
for (int i = 1; i <= 4; i++) {
int nextx = curx + dx[i];
int nexty = cury + dy[i];
if (OutOfBorder(nextx, nexty, m ,n))
continue;
int step = 0;
if (grid[curx][cury] == i) {
step = dis[curx][cury];
} else { // 改变方向
step = dis[curx][cury] + 1;
}
if (step < dis[nextx][nexty]) {
dis[nextx][nexty] = step;
//这个点改变可能导致其他的dis改变,加入队列中继续BFS
if (!vis[nextx][nexty]) { // 下个点不在队列中,就加入队列
qu.offer(new Point(nextx, nexty));
vis[nextx][nexty] = true;
}
}
}
}
return dis[m - 1][n - 1];
}
private boolean OutOfBorder(int x, int y, int m, int n) {
if (x >= 0 && x < m && y >= 0 && y < n)
return false;
return true;
}
class Point {
int x;
int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
}
参考题解:SPFA——BFS的一种扩展