[LeetCode317]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 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.
The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.

For example, given 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.

Note:
There will be at least one building. If it is not possible to build such house according to the above rules, return -1.

Hide Company Tags Google Zenefits
Hide Tags Breadth-first Search
Hide Similar Problems (M) Walls and Gates (H) Best Meeting Point

Discuss:

https://leetcode.com/discuss/questions/oj/shortest-distance-from-all-buildings

这道题一看就知道要用BFS。但有很多细节的地方:比如,最后找出的point必须是所有building都可以到达的,所以如果是:

{1,1}
{0,1}

这种情况就应该return -1;

我们traverse整个grid, 一旦发现1 就开始BFS. 对于第一个building(which is grid[i][j] == 1) 它可以到达的地方是所有为0 的点,一旦它visited过这些点,我们update其为-1。 对于第二个building,我们只能走那些-1的点,为什么呢?因为如果第一个点不能到达某一个点p, 那么这个p已经不满足题目要求:You want to build a house on an empty land which reaches *all* buildings in the shortest amount of distance. 我们没必要去check这个点。。因此最终我们traverse total 这个matrix的时候不仅要跳过那些 total[i][j] == 0 的点(因为这些点是building或者obstacle的位置), 而且我们还要跳过 total[i][j] != canAchieve 的点(因为这些点不能被所有的building到达,其实 canAchieve 这个变量记录了一共有多少building)。。

理清这些思路就可以写出下面的code,40ms:

class Solution {
public:
    int shortestDistance(vector<vector<int>>& grid) {
        if(grid.empty()) return -1;
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> total(m,vector<int>(n,0));// using vector to store information about the total distance for each possible node.
        vector<vector<int>> newGrid = grid;// we dont want to change original matrix;
        int canAchieve = 0, minDist = INT_MAX;
        vector<pair<int, int>> dirs = {{0,1}, {1,0}, {0,-1}, {-1,0}};
        for(int i = 0; i<m; ++i){
            for(int j = 0; j<n; ++j){
                if(grid[i][j] == 1){
                    queue<pair<int, int>> q;
                    q.push(make_pair(i,j));// current 1 position, we start BFS;
                    vector<vector<int>> dist(m,vector<int>(n,0));
                    //using dist to store distance information start from current building.
                    while(!q.empty()){
                        auto cur = q.front();
                        q.pop();
                        for(auto d : dirs){
                            int newX = cur.first+d.first, newY = cur.second+d.second;
                            if(newX<m && newX>=0 && newY<n && newY >=0 && newGrid[newX][newY] == canAchieve){
                                --newGrid[newX][newY];
                                dist[newX][newY] = dist[cur.first][cur.second]+1;
                                total[newX][newY] += dist[newX][newY];
                                q.push(make_pair(newX, newY));
                            }
                        }
                    }
                    --canAchieve;//after each update, we change the node we can achieve by --canAchieve.
                }
            }
        }
        for(int i = 0; i<total.size(); ++i){
            for (int j = 0; j<total[0].size(); ++j) {
                if(total[i][j] && newGrid[i][j] == canAchieve) minDist = min(minDist, total[i][j]);// insure all building can achieve this point!;
            }
        }
        return minDist == INT_MAX ? -1 : minDist;
    }
};

你可能感兴趣的:(LeetCode)