lintcode573- Build Post Office II- hard
Posted jasminemzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lintcode573- Build Post Office II- hard相关的知识,希望对你有一定的参考价值。
Given a 2D grid, each cell is either a wall 2
, an house 1
or empty 0
(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 -1
if 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.
Given a grid:
0 1 0 0 0
1 0 0 2 1
0 1 0 0 0
return 8
, 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.)
之前题目 I 是可以直接算manhattan距离,这里不行,距离要用BFS算了。
算法主体:1.找出所有house放list 2.遍历house做bfs,把距离之和distSum[][]以及空地访问次数visitCnt[][]记录下来. 3.根据visitCnt[][]遍历合格的房子都走得到的空地,访问distSum[][]打擂台决出最小dist。
算法BFS:size的层级遍历。参数传入distSum[][]和visitCnt[][]让所有的BFS能共享这个"全局变量"进行修改。从1出发,BFS出所有的0,每次对0访问次数计数++,层级遍历的step表示从1出发到这个0的距离,让distSum[][]+=steps。另外坐标Point(x,y)这种数据结构不能用HashSet作为和queue搭配的去重set,这时候可以巧妙地自己命名一个boolean[][] hash,如果某个坐标(x,y)被加入queue了,以后不想让这个点被重复加,就赋值hash[x][y] = true; 起到了set的作用。
数据结构:distSum[][] 保存了对于地图中某个空地0,到所有房子1的距离和。 visitCnt[][] 保存了对于地图中某个空地0,能访问到多少个房子1。
细节:1.int WALL EMPTY HOUSE=1 这种常数定义放在大类Solution里,这样保证所有子函数也能访问到这些标志。2.小心全都是房子不能放置office的corner case
public class Solution { /* * @param grid: a 2D grid * @return: An integer */ private class Point{ public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } } private int WALL = 2; private int HOUSE = 1; private int EMPTY = 0; public int shortestDistance(int[][] grid) { // write your code here if (grid == null || grid.length == 0 || grid[0].length == 0) { return -1; } int h = grid.length; int w = grid[0].length; int[][] visitCnt = new int[h][w]; int[][] distSum = new int[h][w]; List<Point> houses = new ArrayList<Point>(); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { if (grid[i][j] == HOUSE) { houses.add(new Point(i,j)); } } } for (Point p : houses) { bfs(grid, p, visitCnt, distSum); } int minDist = Integer.MAX_VALUE; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { //!!!两个条件 if (grid[i][j] != EMPTY || visitCnt[i][j] != houses.size()) { continue; } minDist = Math.min(minDist, distSum[i][j]); } } // !!!CORNER CASE : all 1 or 2 if (minDist == Integer.MAX_VALUE) { return -1; } return minDist; } private void bfs (int[][] grid, Point crt, int[][] visitCnt, int[][] distSum) { int[] dx = {-1, 0, 1, 0}; int[] dy = {0, -1, 0, 1}; boolean[][] hash = new boolean[grid.length][grid[0].length]; Queue<Point> queue = new LinkedList<Point>(); queue.offer(crt); hash[crt.x][crt.y] = true; int steps = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { Point p = queue.poll(); visitCnt[p.x][p.y]++; distSum[p.x][p.y] += steps; for (int dirct = 0; dirct < 4; dirct++) { Point next = new Point (p.x + dx[dirct], p.y + dy[dirct]); // !!!三个条件不要漏 if (isValid(grid, next) && !hash[next.x][next.y] && grid[next.x][next.y] == EMPTY) { queue.offer(next); hash[next.x][next.y] = true; } } } steps++; } } private boolean isValid(int[][] grid, Point point) { int h = grid.length; int w = grid[0].length; return point.x >= 0 && point.x < h && point.y >= 0 && point.y < w; } }
以上是关于lintcode573- Build Post Office II- hard的主要内容,如果未能解决你的问题,请参考以下文章
lintcode574- Build Post Office- hard
[LintCode] 574 Build Post Office II
lintcode-medium-Segment Tree Build