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
Example 1
Input: [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]
Output: 7
Explanation:
In this example, there are three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2).
1 - 0 - 2 - 0 - 1
| | | | |
0 - 0 - 0 - 0 - 0
| | | | |
0 - 0 - 1 - 0 - 0
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.
Example 2
Input: [[1,0],[0,0]]
Output: 1
In this example, there is one buildings at (0,0).
1 - 0
| |
0 - 0
The point (1,0) or (0,1) is an ideal empty land to build a house, as the total travel distance of 1 is minimal. So return 1.
Notes:
This question is labeled as hard in both Leetcode and Lintcode, but actually the idea is pretty straightforward:
1): we can use bfs search for each house, then record the minimum distance results for each "empty" position into a hash map;
2): then we need to go through the hash map, to find the empty position having the minimum sum distances to all the houses.
See the code below:
class Solution {
public:
/**
* @param grid: the 2D grid
* @return: the shortest distance
*/
int shortestDistance(vector<vector<int>> &grid) {
// write your code here
if(!grid.size() || !grid.front().size()) return 0;
int res = INT_MAX, m = grid.size(), n = grid.front().size(), ct = 0;
unordered_map<int, vector<int>> mp;
for(int i=0; i<m; ++i) {
for(int j=0; j<n; ++j) {
if(grid[i][j] == 1) {
++ct;
bfs(grid, i, j, mp);
}
}
}
for(int i=0; i<m; ++i) {
for(int j=0; j<n; ++j) {
if(grid[i][j] == 0 && mp[i*n+j].size() == ct) {
int sum = 0;
for(auto &a : mp[i*n+j]) sum += a;
res = min(res, sum);
}
}
}
return res==INT_MAX? -1 : res;
}
private:
void bfs(vector<vector<int>>& grid, int i, int j, unordered_map<int, vector<int>>& mp) {
int m = grid.size(), n = grid.front().size();
vector<vector<int>> visit(m, vector<int>(n, 0));
queue<pair<int, int>> q;
q.push({i, j});
visit[i][j] = 1;
vector<int> dirs = {-1, 0, 1, 0, -1};
int step = 1;
while(q.size()) {
int k = q.size();
for(int i=0; i<k; ++i) {
auto t = q.front();
q.pop();
for(int j=0; j+1<dirs.size(); ++j) {
int a = t.first + dirs[j], b = t.second + dirs[j+1];
if(a<0 || a>=m || b<0 || b>=n || grid[a][b] != 0 || visit[a][b]) continue;
q.push({a, b});
visit[a][b] = 1;
// cout<<a<<" "<<b<<" "<<step<<endl;
mp[a*n+b].push_back(step);
}
}
++step;
}
}
};
No comments:
Post a Comment