[LeetCode] Shortest Distance from All Buildings

317. Shortest Distance from All Buildings

You are given an m x n grid grid of values 0, 1, or 2, where:

  • each 0 marks an empty land that you can pass by freely,
  • each 1 marks a building that you cannot pass through, and
  • each 2 marks an obstacle that you cannot pass through.

You want to build a house on an empty land that reaches all buildings in the shortest total travel distance. You can only move up, down, left, and right.

Return the shortest travel distance for such a house. If it is not possible to build such a house according to the above rules, return -1.

The total travel distance is the sum of the distances between the houses of the friends and the meeting point.

The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.

  • Time : O(nm * buildings)
  • Space : O(nm)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Solution {
vector<vector<int>> distance;
unordered_set<int> meetBuildingcount;
vector<vector<bool>> notStuck;
int dx[4] = {0,1,0,-1}, dy[4] = {-1,0,1,0};

void check(vector<vector<int>>& grid, int y, int x) {
int n = grid.size(), m = grid[0].size();
queue<pair<int, int>> q; q.push({y,x});
notStuck[y][x] = true;
while(!q.empty()) {
int sz = q.size();
while(sz--) {
auto [cy, cx] = q.front(); q.pop();
for(int i = 0; i < 4; i++) {
int ny = cy + dy[i], nx = cx + dx[i];
if(0 <= ny and ny < n and 0 <= nx and nx < m and !grid[ny][nx] and !notStuck[ny][nx]) {
notStuck[ny][nx] = true;
q.push({ny,nx});
}
}
}
}
}

void bfs(vector<vector<int>>& grid, int y, int x) {
int n = grid.size(), m = grid[0].size();
vector<vector<bool>> v(n, vector<bool>(m,false));
queue<pair<int, int>> q; q.push({y,x});
int dis = 1;
int cnt = 0;
while(!q.empty()) {
int sz = q.size();
while(sz--) {
auto [cy, cx] = q.front(); q.pop();
for(int i = 0; i < 4; i++) {
int ny = cy + dy[i], nx = cx + dx[i];
if(0 <= ny and ny < n and 0 <= nx and nx < m and !grid[ny][nx] and !v[ny][nx]) {
v[ny][nx] = true;
q.push({ny,nx});
distance[ny][nx] += dis;
}
if(0 <= ny and ny < n and 0 <= nx and nx < m and grid[ny][nx] == 1 and !v[ny][nx]) {
v[ny][nx] = true;
cnt++;
}
}
}
dis++;
}
meetBuildingcount.insert(cnt);
}
public:
int shortestDistance(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size(), building = 0;
distance = vector<vector<int>>(n,vector<int>(m,0));
notStuck = vector<vector<bool>>(n,vector<bool>(m,0));
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(grid[i][j] == 1) {
building++;
bfs(grid,i,j);
}
if(meetBuildingcount.size() > 1) return -1;
}
}
int res = INT_MIN, y, x;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(!grid[i][j] and distance[i][j] and res < distance[i][j]) {
res = distance[i][j];
y = i, x = j;
}
}
}
if(res != INT_MIN) check(grid,y,x);
res = INT_MAX;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(!grid[i][j] and distance[i][j] and notStuck[i][j]) res = min(res, distance[i][j]);
}
}
return res == INT_MAX ? -1 : res;
}
};
Author: Song Hayoung
Link: https://songhayoung.github.io/2022/02/16/PS/LeetCode/shortest-distance-from-all-buildings/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.