317. Shortest Distance from All Buildings

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:

  1. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值