You want to build a house on anemptyland 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 values0,1or2, 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):
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.
L573 Build Post Office II
Given a 2D grid, each cell is either a wall2, an house1or empty0(the number zero, one, two), find a place to build a post office so that the sum of the distance from the post office to all the houses is smallest.
Return the smallest sum of distance. Return-1if it is not possible.
Notice
You cannot pass through wall and house, but can pass through empty.
You only build post office on an empty.
Example
Given a grid:
0 1 0 0 0
1 0 0 2 1
0 1 0 0 0
return8, You can build at(1,1). (Placing a post office at (1,1), the distance that post office to all the house sum is smallest.)
这题是逆向bfs,正向的做法是,从每个空地到每个house做一次bfs,这样复杂度会是O(m * n * m * n)。不过因为通常house比空地少,所以我们从house出发对每个空地做一次bfs。这样复杂度就会变成house number × m × n。这里我们要用几个变量辅助。首先要用一个reach矩阵来记录每个空地能被多少个房子visit到,最后找邮局位置时用来判断是否可达。然后用另外一个矩阵dist来记录bfs的距离。当然每次bfs都要带一个visited矩阵防止走回头路。
publicintshortestDistance(int[][] grid) {if (grid ==null||grid.length==0|| grid[0].length==0) {return-1; }// basically use bfs to record distance from 1 (house) to each 0.// this question happen to have more 0 than 1, so it's quicker to do bfs on house (1)int n =grid.length;int m = grid[0].length;int[][] dist =newint[n][m];// track distanceint[][] reach =newint[n][m];// track whether the location is reachable from all housesint houseNum =0; // use at the end to find out which location is reachable in reach[][]int[] x = {0,0,1,-1};int[] y = {1,-1,0,0};for (int i =0; i < n; i++) {for (int j =0; j < m; j++) {if (grid[i][j] ==1) { // do bfs for houses houseNum++;boolean[][] visited =newboolean[n][m];Queue<Integer> queue =newLinkedList<>();int cur = i * m + j;// easier way to bfs matrix, don't have to make a class pair (i, j) visited[i][j] =true;queue.offer(cur);int level =0; while (!queue.isEmpty()) {int size =queue.size();for (int s =0; s < size; s++) { cur =queue.poll();int row = cur / m;int col = cur % m;// bfs on surrounding cellsfor (int k =0; k <4; k++) {int nexti = row + x[k];int nextj = col + y[k];if (inBound(grid, nexti, nextj)&&!visited[nexti][nextj] && grid[nexti][nextj] ==0) { visited[nexti][nextj] =true; reach[nexti][nextj]++; dist[nexti][nextj] += level +1;queue.offer(nexti * m + nextj); } } } level++; } } } }int min =Integer.MAX_VALUE;for (int i =0; i < n; i++) {for (int j =0; j < m; j++) {if (reach[i][j] == houseNum && grid[i][j] ==0) { min =Math.min(min, dist[i][j]); } } }return min ==Integer.MAX_VALUE?-1: min;}privatebooleaninBound(int[][] grid,int r,int c) {if (r <0|| c <0|| r >=grid.length|| c >= grid[0].length) {returnfalse; }returntrue;}