317. 离建筑物最近的距离
题目:
你是个房地产开发商,想要选择一片空地 建一栋大楼。你想把这栋大楼够造在一个距离周边设施都比较方便的地方,通过调研,你希望从它出发能在 最短的距离和 内抵达周边全部的建筑物。请你计算出这个最佳的选址到周边全部建筑物的 最短距离和。
注意:
你只能通过向上、下、左、右四个方向上移动。
给你一个由 0、1 和 2 组成的二维网格,其中:
0 代表你可以自由通过和选择建造的空地
1 代表你无非通行的建筑物
2 代表你无非通行的障碍物
示例:
输入: [[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
输出: 7
解析:
给定三个建筑物 (0,0)、(0,4) 和 (2,2) 以及一个位于 (0,2) 的障碍物。
由于总距离之和 3+3+1=7 最优,所以位置 (1,2) 是符合要求的最优地点,故返回7。
注意:
你会保证有至少一栋建筑物,如果无法按照上述规则返回建房地点,则请你返回 -1。
解答:
做不出来,先想到了从每个0开始DFS,但觉得复杂度太高了。
正确做法是从每个1开始BFS,因为要找的就是达到所有建筑物的最短距离和。所以从每个建筑物分别开始BFS,计算的达到某节点的距离,就是该建筑物到达该节点的最短距离。
从所有的建筑物BFS遍历所有节点,最短距离和就算出来了。
写到这里,发现以前做过一道类似的题目,好像也是类似的情景,需要从目的地分别开始向所有出发地BFS。
总结一下:最短距离/最短距离和的题目,先想一下用BFS是不是更好做,不要什么题一上来就知道DFS。。
代码:
1 class Solution { 2 public: 3 int shortestDistance(vector<vector<int>>& grid) { 4 int m=grid.size(),n=grid[0].size(); 5 if(m==0 or n==0){return 0;} 6 vector<vector<int>> reached_buildings(m,vector<int>(n,0));//记录有几个建筑物能到达当前位置 7 vector<vector<int>> path_cnt(m,vector<int>(n,0));//记录所有建筑物到当前位置的距离总和 8 vector<vector<int>> dif={{0,1},{0,-1},{1,0},{-1,0}}; 9 vector<vector<bool>> visited(m,vector<bool>(n,false)); 10 int build_cnt=0,res=INT32_MAX; 11 bool flag=false; 12 for(int i=0;i<m;++i){ 13 for(int j=0;j<n;++j){ 14 if(grid[i][j]!=1){continue;} 15 build_cnt++; 16 res=INT_MAX; 17 queue<pair<int,int>> my_que; 18 my_que.push({i,j}); 19 int cur_path_len=1; 20 while(not my_que.empty()){ 21 int cur_siz=my_que.size(); 22 for(int k=0;k<cur_siz;++k){ 23 auto cur=my_que.front(); 24 my_que.pop(); 25 for(auto& d:dif){ 26 int x=cur.first+d[0],y=cur.second+d[1]; 27 if(x>=0 and x<m and y>=0 and y<n and visited[x][y]==flag and grid[x][y]==0){ 28 my_que.push({x,y}); 29 visited[x][y]=!flag; 30 path_cnt[x][y]+=cur_path_len; 31 reached_buildings[x][y]+=1; 32 if(reached_buildings[x][y]==build_cnt){ 33 res=min(res,path_cnt[x][y]); 34 } 35 } 36 } 37 } 38 cur_path_len++; 39 } 40 flag=!flag; 41 } 42 } 43 return res==INT_MAX?-1:res; 44 } 45 };
进击的小🐴农