目录
- 0.原理讲解
- 1.矩阵
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 2.飞地的数量
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 3.地图中的最高点
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 4.地图分析
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
0.原理讲解
-
注意:只要是用**BFS解决的最短路径问题,都要求边权为一(边权值相同)**
-
单源最短路径
- 把起点加入到队列中
- 一层一层的往外扩展
-
多源BFS:用BFS解决边权为一的多源最短路径问题
-
法一:暴力解,把多源最短路径问题转化为若干个单源最短路问题
- 效率低,大概率会超时
-
法二:把所有的源点当成一个"超级源点"
- 此时问题就变成了「单源最短路径」问题
- 此时问题就变成了「单源最短路径」问题
-
"超级源点"的正确性?感性理解:
- 同时从几个源点出发,会存在"舍弃"几个"不好的点"的现象
- 远的源点走一步肯定没有近的源点走一步好,所以相当于舍去了远的源点
-
多源BFS如何代码实现?
- 把所有的源点加入到队列里面
- 一层一层的往外扩展
1.矩阵
1.题目链接
- 矩阵
2.算法原理详解
-
思路一:一个位置一个位置求
- 不用想,这么暴力肯定超时:P
-
思路二:多源BFS + 正难则反 -> 把所有的0当成起点,1当成终点
- 把所有的0位置加入到队列中
- 一层一层的向外拓展即可
-
为什么正着做会很困难呢?
- 正着做虽然能找到0,但是想把距离存下来,会很难
- 并且也无法知道是哪个1到了0,距离是多少
-
为什么本题用到了多源BFS呢?
- 0是有很多个的,怎么才能保证遇到的1距离这⼀个0是最近的?
- 先把所有的0都放在队列中,把它们当成⼀个整体,每次把当前队列⾥⾯的所有元素向外扩展⼀次
-
细节:在单源最短路径中需要:
bool visit[i][j]
、step
、sz
,而在多源BFS中,只需要一个int dist[i][j]
就可以替代这三者的功能- 为什么可以替代
bool visit[i][j]
?- 将
dist[][]
初始化为-1
,-1
表示没有搜索过 dist[i][j] != -1
则为最短距离
- 将
- <为什么可以替代
step
?- 从
(a, b) -> (x, y)
,dist[a][b]
存储了dist[x][y]
上一步的距离dist[x][y] = dist[a][b] + 1
- 从
- 为什么可以替代
sz
?- 因为不强制一定要按层一层一层出队列,可以一个元素一个元素的往外扩展
- 不需要知道此时是哪一层,
dist[i][j]
已经标记了现在是属于哪一层
- 为什么可以替代
3.代码实现
vector<vector<int>> UpdateMatrix(vector<vector<int>>& mat)
{int n = mat.size(), m = mat[0].size();// dist[i][j] == -1 未搜索过// dist[i][j] != -1 最短距离vector<vector<int>> dist(n, vector<int>(m, -1));queue<pair<int, int>> q;// 将所有源点加入到队列中for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(mat[i][j] == 0){q.push({i, j});dist[i][j] = 0;}}}// 多源BFSwhile(q.size()){auto [a, b] = q.front();q.pop();// 将下一层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m && dist[x][y] == -1){dist[x][y] = dist[a][b] + 1;q.push({x, y});}}}return dist;
}
2.飞地的数量
1.题目链接
- 飞地的数量
2.算法原理详解
- 思路一:一个一个去判断
- 不用想,这么暴力肯定超时:P
- 思路二:多源BFS + 正难则反 -> 从边界上的1开始,做一次搜索
- 多源BFS结束后,重新遍历一次数组,最后剩下来的就都是飞地
- 多源BFS结束后,重新遍历一次数组,最后剩下来的就都是飞地
3.代码实现
int NumEnclaves(vector<vector<int>>& grid)
{int n = grid.size(), m = grid[0].size();vector<vector<bool>> visit(n, vector<bool>(m, false));queue<pair<int, int>> q;// 将所有边界1入队列for(int i = 0; i < n; i++){if(grid[i][0] == 1){q.push({i, 0});visit[i][0] = true;}if(grid[i][m - 1] == 1){q.push({i, m - 1});visit[i][m - 1] = true;}}for(int i = 0; i < m; i++){if(grid[0][i] == 1){q.push({0, i});visit[0][i] = true;}if(grid[n - 1][i] == 1){q.push({n - 1, i});visit[n - 1][i] = true;}}// 多源BFSwhile(q.size()){auto [a, b] = q.front();q.pop();// 下一层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m \&& grid[x][y] == 1 && !visit[x][y]){visit[x][y] = true;q.push({x, y});}}}// 遍历计数int count = 0;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(grid[i][j] == 1 && !visit[i][j]){count++;}}}return count;
}
3.地图中的最高点
1.题目链接
- 地图中的最高点
2.算法原理详解
- "01矩阵"变形题,直接多源BFS即可
3.代码实现
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};
public:vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {int n = isWater.size(), m = isWater[0].size();vector<vector<int>> dist(n, vector<int>(m, -1));queue<pair<int, int>> q;// 将边界水域入队列for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(isWater[i][j]){dist[i][j] = 0;q.push({i, j});}}}// 多源BFSwhile(q.size()){auto [a, b] = q.front();q.pop();// 下一层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m && dist[x][y] == -1){dist[x][y] = dist[a][b] + 1;q.push({x, y});}}}return dist;}
};
4.地图分析
1.题目链接
- 地图分析
2.算法原理详解
- "01矩阵"变形题,直接多源BFS即可
3.代码实现
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};
public:int maxDistance(vector<vector<int>>& grid) {int n = grid.size();vector<vector<int>> dist(n, vector(n, -1));queue<pair<int, int>> q;// 将陆地入队列for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){if(grid[i][j]){dist[i][j] = 0;q.push({i, j});}}}// 多源BFSint ret = -1;while(q.size()){auto [a, b] = q.front();q.pop();// 下层入队列for(int i = 0; i < 4; i++){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < n && dist[x][y] == -1){dist[x][y] = dist[a][b] + 1;q.push({x, y});ret = max(ret, dist[x][y]);}}}return ret;}
};