zoukankan      html  css  js  c++  java
  • lintcode573- Build Post Office II- hard

    Given a 2D grid, each cell is either a wall 2, an house 1or 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.
    Example

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

    Challenge 

    Solve this problem within O(n^3) time.

    之前题目 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;
        }
    }
  • 相关阅读:
    exports 与 module.exports 的区别
    [读书笔记] JavaScript设计模式: 单例模式
    mybaits及mybaits generator 插件使用指南(亲测原创)
    【转】系统吞吐量等知识相关
    java的JDBC驱动使用链接数据库
    java程序引用别的jar包打包方法
    ftp服务器不能上传文件故障
    lftp下载文件无法覆盖,提示" file already existst and xfer:clobber is unset" 问题解决
    jar/war文件的解释
    linux 自动输入用户名和密码 ftp
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/7750017.html
Copyright © 2011-2022 走看看