317. Shortest Distance from All Buildings
You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:
Each 0 marks an empty land which you can pass by freely.
Each 1 marks a building which you cannot pass through.
Each 2 marks an obstacle which you cannot pass through.
Example:
Input: [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]
1 - 0 - 2 - 0 - 1
| | | | |
0 - 0 - 0 - 0 - 0
| | | | |
0 - 0 - 1 - 0 - 0
Output: 7
Explanation: Given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2),
the point (1,2) is an ideal empty land to build a house, as the total
travel distance of 3+3+1=7 is minimal. So return 7.
Note:
- There will be at least one building. If it is not possible to build such house according to the above rules, return -1.
方法0: bfs,TLE
思路:
首先遍历一遍,记住一共有多少楼,有的bfs不能遍历到所有的楼,不能计入合法结果,在bfs中要统计reached。之后在每一个0点,发起bfs, 并且累加计算和所有楼(1 or 2)之间的距离。保持一个visited的矩阵来记录当前格点和始发格点的距离。在每一个点上,如果是0 对上下左右发起bfs,检查其是否visited,如果没有,将其距离改变成上一个距离+1,否则跳过。如果是 1,将此时的distance累加。在循环过程中统计一个全球最小距离。如果发现最终结果是initialize的值, INT_MAX,那么说明没有可以建楼的地方,返回-1。这个每个0都建一个二维visited的方法,在十多个数据点上,TLE了。
class Solution {
public:
int shortestDistance(vector<vector<int>>& grid) {
int result = INT_MAX;
int total = 0;
for (int i = 0; i < grid.size(); i ++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 1) {
total++;
}
}
}
for (int i = 0; i < grid.size(); i ++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == 0) {
bfs(grid, i, j, result, total);
}
}
}
return (result == INT_MAX) ? -1 : result;
}
void bfs(vector<vector<int>> & grid, int i, int j, int & result, int total) {
vector<vector<int>> visited(grid.size(), vector<int>(grid[0].size(), -1));
visited[i][j] = 0;
queue<pair<int, int>> q;
q.push({i, j});
int dist = 0;
int reached = 0;
vector<vector<int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
while (!q.empty()) {
auto top = q.front();
q.pop();
for (auto dir: dirs) {
i = top.first;
j = top.second;
int x = top.first + dir[0];
int y = top.second + dir[1];
if (x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size() || visited[x][y] != -1) continue;
visited[x][y] = visited[i][j] + 1;
if (grid[x][y] == 1) {
dist += visited[x][y];
reached ++;
}
else if (grid[x][y] == 0) {
q.push({x, y});
}
}
}
if (dist != 0 && dist < result && reached == total) {
result = dist;
}
return;
}
};
方法2: bfs
grandyang:https://www.cnblogs.com/grandyang/p/5297683.html
思路:
class Solution {
public:
int shortestDistance(vector<vector<int>>& grid) {
int result = INT_MAX;
int total = 0;
int m = grid.size();
int n = grid[0].size();
vector<vector<int>> dist(m, vector<int>(n, 0));
vector<vector<int>> reached(m, vector<int>(n, 0));
vector<vector<int>> dirs = {{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) {
total++;
vector<vector<bool>> visited(m, vector<bool>(n, false));
queue<pair<int, int>> q;
q.push({i, j});
int level = 1;
while (!q.empty()) {
int s = q.size();
for (int k = 0; k < s; k++){
auto top = q.front();
q.pop();
for (auto dir: dirs) {
int x = top.first + dir[0];
int y = top.second + dir[1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y] || grid[x][y] != 0) continue;
visited[x][y] = true;
dist[x][y] += level;
reached[x][y]++;
q.push({x, y});
}
}
level++;
}
}
}
}
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0 && reached[i][j] == total) {
result = min(result, dist[i][j]);
}
}
}
return (result == INT_MAX) ? -1 : result;
}
};
方法3: bfs
discussion:https://leetcode.com/problems/shortest-distance-from-all-buildings/discuss/76880/36-ms-C%2B%2B-solution
grandyang:https://www.cnblogs.com/grandyang/p/5297683.html