矩阵多源广搜的引入
题目分析:
矩阵中
0
1
2
三种元素
三种元素的出现次数和是否出现不确定(初始可能有多个腐烂的橘子)
考虑是否需要剪枝:全0
结果需要返回0
,只要最终包含的有1
,返回-1
其他的情况则按照橘子腐烂的方向来确定全部腐烂的时间
题目转换:即把所有没有腐烂的橘子
(1)
,找到距离他最近的已经腐烂的橘子(2)
,最后整个矩阵(除去值0
的位置)遍历完之后,找出最长路径,所以问题就被转换为矩阵的多源最短路径问题
.使用到的算法矩阵的多源广搜
代码及注释(c++)
class Solution {
public:
int orangesRotting(vector<vector<int>>& mat) {
int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
queue<pair<int, int>> q;
int m = mat.size(), n = mat[0].size();
vector<vector<int>> seen(m, vector<int>(n));//访问标志
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (mat[i][j] == 2) {//多源入队,腐烂的橘子为源点
q.emplace(i, j);
seen[i][j] = 1;
}
}
}
int minute = 0; //剪枝,使用时间初始化0,处理全0时的特殊情况
//minute其实就是记录的每次广搜的位置距离初始源点的最短路
int len = 0;//每次更新的新源点个数,按照题意是1min是同时传播腐烂的。
// 广度优先搜索
while (!q.empty()) {
len = q.size();//每次更新的新源点个数
for(int k = 0; k < len; k++)//对这次源点传播腐烂维护数组
{
auto [i, j] = q.front();
q.pop();
for (int d = 0; d < 4; ++d) {
int ni = i + dirs[d][0];
int nj = j + dirs[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && !seen[ni][nj] && mat[ni][nj])
{
mat[ni][nj] = 2;
q.emplace(ni, nj);
seen[ni][nj] = 1;
}
}
}
if(!q.empty())//最后一次遍历结束minute不需要+1
minute++;
}
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (mat[i][j] == 1) {
return -1;//存在1即返回-1
}
}
}
return minute;
}
};