题目地址:
https://leetcode.com/problems/shortest-distance-from-all-buildings/
给定一个二维矩阵,只含 0 , 1 , 2 0,1,2 0,1,2, 0 0 0代表空地, 1 1 1代表建筑, 2 2 2代表障碍物。要求在一个空地建个房屋,使得房屋到所有建筑物的路径长度之和达到最小。路径的每一步只能向上下左右走,并且只能走到空地上。如果存在房屋的建造方案,则返回最短路径长度总和;否则返回 − 1 -1 −1。
思路是BFS。可以从每个建筑物出发,遍历一下其所能到达的空地,并累加该空地与之的路径距离。遍历的同时要注意,如果一个某个空地这个建筑物到不了,那么说明这个空地是不能建房屋的,最后统计的时候要把这个空地排除在外。代码如下:
class Solution {
public:
using PII = pair<int, int>;
#define x first
#define y second
int shortestDistance(vector<vector<int>>& g) {
int m = g.size(), n = g[0].size();
int sum_dist[m][n];
memset(sum_dist, 0, sizeof sum_dist);
auto bfs = [&](int x, int y) {
bool vis[m][n];
memset(vis, 0, sizeof vis);
vis[x][y] = true;
queue<PII> q;
q.push({x, y});
int step = 0;
while (q.size()) {
step++;
for (int _ = q.size(); _; _--) {
auto p = q.front(); q.pop();
int x = p.x, y = p.y;
static int d[] = {-1, 0, 1, 0, -1};
for (int k = 0; k < 4; k++) {
int nx = x + d[k], ny = y + d[k + 1];
if (0 <= nx && nx < m && 0 <= ny && ny < n && !vis[nx][ny] &&
!g[nx][ny]) {
vis[nx][ny] = true;
q.push({nx, ny});
if (~sum_dist[nx][ny]) sum_dist[nx][ny] += step;
}
}
}
}
// 如果有空地不能到达,则这个空地不能参与统计
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (!g[i][j] && !vis[i][j]) sum_dist[i][j] = -1;
};
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (g[i][j] == 1) bfs(i, j);
int res = INT_MAX;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (!g[i][j] && ~sum_dist[i][j]) res = min(res, sum_dist[i][j]);
return res == INT_MAX ? -1 : res;
}
};
时间复杂度 O ( k m n ) O(kmn) O(kmn), k k k为建筑物数量,空间 O ( m n ) O(mn) O(mn)。