题目:题目链接
思路:直接bfs就好。每一分钟都拓展当前所有的腐烂橙子,然后直到不能拓展,再看是否还有新鲜橙子。看代码吧:
class Solution {
public:
int m, n;
bool isInBoard(int x, int y) {//判断是否在网格内
return (x < m&& x >= 0) && (y < n&& y >= 0);
}
int orangesRotting(vector<vector<int>>& grid) {
m = grid.size();
n = grid[0].size();
int cnt = 0, time = 0;//cnt表示新鲜橙子的个数,time表示分钟数
queue<pair<int, int> >q;//存放每个腐烂橙子的坐标
vector<vector<int> >vis(m, vector<int>(n, 0));//标记该坐标是否访问过
vector<vector<int> >dis = { {0,-1},{0,1},{1,0},{-1,0} };//可以向四个方向拓展
for (int i = 0; i < m; ++i) {//查找新鲜橙子和腐烂橙子
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) cnt++;
if (grid[i][j] == 2) {//把腐烂橙子放入队列q中
q.push(make_pair(i, j));
vis[i][j] = 1;
}
}
}
if (cnt == 0) return 0;//没有新鲜橙子
while (!q.empty()) {
int size = q.size();//当前队列的大小
for (int j = 0; j < size; ++j) {//在每一分钟把当前队列中的所有腐烂橙子都进行拓展
auto tmp = q.front();
q.pop();
for (int i = 0; i < dis.size(); ++i) {
int now_x = tmp.first + dis[i][0];
int now_y = tmp.second + dis[i][1];
if (isInBoard(now_x, now_y) && !vis[now_x][now_y]) {//坐标合法,且没有被拓展过
if (grid[now_x][now_y] == 1) {//因为新鲜橙子可以变成腐烂的,空的和已腐烂的都无变化
grid[now_x][now_y] = 2;
cnt--;
q.push(make_pair(now_x, now_y));
}
vis[now_x][now_y] = 1;//对于当前拓展的结点不管是0,1,2都标记为访问,避免重复访问
}
}
}
time++;//分钟数增加
}
if (cnt == 0) return time - 1;//注意:这里为什么time-1,而不是time。因为当新鲜橙子都腐烂时队列时不为空的。只有等最后一批腐烂橙子拓展完才为空。
return -1;
}
};
注意:time最后要减1,因为while循环终止条件是队列q为空,当最后一个新鲜橙子变成腐烂橙子时,队列是不为空的,还有这个腐烂橙子,直至下一秒这个腐烂橙子也拓展完。所以time比实际时间多1。当然在while中加一个cnt>0也可以。
搞定。加油加油加油加油加油加油!!!!