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.

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.

这道题给我们了一些建筑物的坐标和一些障碍物的坐标,让我们找一个位置,使其到所有建筑物的曼哈顿距离之和最小,起初我觉得这题应该算Best Meeting Point那道题的拓展,不同之处在于这道题有了障碍物的存在,这样就使得直接使用曼哈顿距离的计算公式变得不可行,因为在有些情况下,障碍物完全封死了某个建筑物,那么这时候应该返回-1。所以这道题只能使用遍历迷宫的思想来解,那么这题就和之前那道Walls and Gates很类似,但是这道题用DFS就会很麻烦,因为我们的目标是要建立Distance Map,所以BFS的特性使得其非常适合建立距离场,而DFS由于是沿着一个方向一股脑的搜索,然后会面临着更新距离的问题,只有当递归函数都调用结束后,距离场才建立好,那么我们累加距离场时又得整个遍历一遍,非常不高效。主要原因还是由于DFS的搜索方式不适合距离场,因为BFS遍历完一个点后,不会再来更改这个点的值,而DFS会反复的更改同一个点的值,我强行用DFS写出的方法无法通过OJ最后一个大集合,所以这道题还是老老实实地用BFS来解题吧,还是需要借助queue来遍历,我们对于每一个建筑的位置都进行一次全图的BFS遍历,每次都建立一个dist的距离场,由于我们BFS遍历需要标记应经访问过的位置,而我们并不想建立一个visit的二维矩阵,那么怎么办呢,这里用一个小trick,我们第一遍历的时候,都是找0的位置,遍历完后,我们将其赋为-1,这样下一轮遍历我们就找-1的位置,然后将其都赋为-2,以此类推直至遍历完所有的建筑物,然后在遍历的过程中更新dist和sum的值,注意我们的dist算是个局部变量,每次都初始化为grid,真正的距离场累加在sum中,由于建筑的位置在grid中是1,所以dist中初始化也是1,累加到sum中就需要减1,我们用sum中的值来更新结果res的值,最后根据res的值看是否要返回-1,参见代码如下:

解法一:

class Solution {
public:
int shortestDistance(vector<vector<int>>& grid) {
int res = INT_MAX, val = , m = grid.size(), n = grid[].size();
vector<vector<int>> sum = grid;
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
for (int i = ; i < grid.size(); ++i) {
for (int j = ; j < grid[i].size(); ++j) {
if (grid[i][j] == ) {
res = INT_MAX;
vector<vector<int>> dist = grid;
queue<pair<int, int>> q;
q.push({i, j});
while (!q.empty()) {
int a = q.front().first, b = q.front().second; q.pop();
for (int k = ; k < dirs.size(); ++k) {
int x = a + dirs[k][], y = b + dirs[k][];
if (x >= && x < m && y >= && y < n && grid[x][y] == val) {
--grid[x][y];
dist[x][y] = dist[a][b] + ;
sum[x][y] += dist[x][y] - ;
q.push({x, y});
res = min(res, sum[x][y]);
}
}
}
--val;
}
}
}
return res == INT_MAX ? - : res;
}
};

下面这种方法也是网上比较流行的解法,我们还是用BFS来做,其中dist是累加距离场,cnt表示某个位置已经计算过的建筑数,变量buildingCnt为建筑的总数,我们还是用queue来辅助计算,注意这里的dist的更新方式跟上面那种方法的不同,这里的dist由于是累积距离场,所以不能用dist其他位置的值来更新,而是需要直接加上和建筑物之间的距离,这里用level来表示,每遍历一层,level自增1,这样我们就需要所加个for循环,来控制每一层中的level值是相等的,参见代码如下:

解法二:

class Solution {
public:
int shortestDistance(vector<vector<int>>& grid) {
int res = INT_MAX, buildingCnt = , m = grid.size(), n = grid[].size();
vector<vector<int>> dist(m, vector<int>(n, )), cnt = dist;
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] == ) {
++buildingCnt;
queue<pair<int, int>> q;
q.push({i, j});
vector<vector<bool>> visited(m, vector<bool>(n, false));
int level = ;
while (!q.empty()) {
int size = q.size();
for (int s = ; s < size; ++s) {
int a = q.front().first, b = q.front().second; q.pop();
for (int k = ; k < dirs.size(); ++k) {
int x = a + dirs[k][], y = b + dirs[k][];
if (x >= && x < m && y >= && y < n && grid[x][y] == && !visited[x][y]) {
dist[x][y] += level;
++cnt[x][y];
visited[x][y] = true;
q.push({x, y});
}
}
}
++level;
}
}
}
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] == && cnt[i][j] == buildingCnt) {
res = min(res, dist[i][j]);
}
}
}
return res == INT_MAX ? - : res;
}
};

类似题目:

Best Meeting Point

Walls and Gates

参考资料:

https://leetcode.com/discuss/74453/36-ms-c-solution

https://discuss.leetcode.com/topic/31925/java-solution-with-explanation-and-time-complexity-analysis/2

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Shortest Distance from All Buildings 建筑物的最短距离的更多相关文章

  1. [LeetCode] 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 dis ...

  2. LeetCode Shortest Distance from All Buildings

    原题链接在这里:https://leetcode.com/problems/shortest-distance-from-all-buildings/ 题目: You want to build a ...

  3. [LeetCode] Shortest Distance from All Buildings Solution

    之前听朋友说LeetCode出了一道新题,但是一直在TLE,我就找时间做了一下.这题是一个比较典型的BFS的题目,自己匆忙写了一个答案,没有考虑优化的问题,应该是有更好的解法的. 原题如下: You ...

  4. leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings

    542. 01 Matrix https://www.cnblogs.com/grandyang/p/6602288.html 将所有的1置为INT_MAX,然后用所有的0去更新原本位置为1的值. 最 ...

  5. [Locked] Shortest Distance from All Buildings

    Shortest Distance from All Buildings You want to build a house on an empty land which reaches all bu ...

  6. [LeetCode] Shortest Distance to a Character 到字符的最短距离

    Given a string S and a character C, return an array of integers representing the shortest distance f ...

  7. Shortest Distance from All Buildings

    You want to build a house on an empty land which reaches all buildings in the shortest amount of dis ...

  8. [Swift]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 dis ...

  9. LeetCode 317. Shortest Distance from All Buildings

    原题链接在这里:https://leetcode.com/problems/shortest-distance-from-all-buildings/ 题目: You want to build a ...

随机推荐

  1. Java中的泛型 (上) - 基本概念和原理

    本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...

  2. 【中文分词】二阶隐马尔可夫模型2-HMM

    在前一篇中介绍了用HMM做中文分词,对于未登录词(out-of-vocabulary, OOV)有良好的识别效果,但是缺点也十分明显--对于词典中的(in-vocabulary, IV)词却未能很好地 ...

  3. shiro的使用1 简单的认证

    最近在重构,有空学了一个简单的安全框架shiro,资料比较少,在百度和google上能搜到的中文我看过了,剩下的时间有空会研究下官网的文章和查看下源码, 简单的分享一些学习过程: 1,简单的一些概念上 ...

  4. java socket编程(li)

    一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以 ...

  5. 来玩Play框架03 模板

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在上一章节中,我把字符串通过ok()返回给客户.我可以把一个完整的html页面放入 ...

  6. Mysql增加、删除和修改列属性和约束,和一些有用的查询语句

    最近在整理关于MySql的东西,把一些需要记录的东西写下来,以便以后查询和浏览,以下是一些操作技巧.添加表字段alter table` 表名称` add transactor varchar(10) ...

  7. CSS类似微软中国首页的竖向选项卡

    效果体验:http://hovertree.com/texiao/css/24/ 源码下载:http://hovertree.com/h/bjaf/hardklps.htm 代码如下: <!DO ...

  8. [JS,Canvas]日历时钟

    [JS,Canvas]日历时钟 Html: <!doctype html> <html> <head> <meta charset="UTF-8&q ...

  9. JQ实现判断iPhone、Android设备

    最近做了一版微信宣传页,通过JQ来判断设备,并进行下载 微信内置浏览器对下载链接进行了屏蔽,所以先进行判断,如果是微信内置浏览器,则跳转应用宝链接,如果不是,则判断是iPhone/Adroid/PC ...

  10. 离开Autodesk,开启新篇章

    我已经离开了Autodesk,开启新篇章.在过去7年多时间中,我先后支持Autodesk 基础设施相关产品的开发,包括MapGuide/AIMS,Map3D,Civil 3D,Infraworks等, ...