Build Post Office

Description

Given a 2D grid, each cell is either an house  1 or empty  0 (the number zero, one), find the place to build a post office, the distance that post office to all the house sum is smallest. Return the smallest distance. Return  -1 if it is not possible.
  • You can pass through house and empty.
  • You only build post office on an empty.
  • The distance between house and the post office is Manhattan distance

Example

Example 1:

Input:[[0,1,0,0],[1,0,1,1],[0,1,0,0]]
Output: 6
Explanation:
Placing a post office at (1,1), the distance that post office to all the house sum is smallest.

Example 2:
Input:[[0,1,0],[1,0,1],[0,1,0]]
Output: 4
Explanation:
Placing a post office at (1,1), the distance that post office to all the house sum is smallest.
Ideas:

method one:

  • Since the problem as required between two points represented as the distance d (i, j) = | xi-xj | + | yi-yj |, can be calculated separately in x and y directions, and then summed to achieve a one-dimensional direction can be calculated.
  • First traverse grid squares is 1, the horizontal and vertical coordinates thereof, i.e., i and j are stored and sorted to find the following easy calculation. And then use sumx Sumy prefix and, on behalf of the origin to x sumx direction and distance, sumy empathy each point.
  • Again traversing the grid, currently at 0, the position of the first binary search direction i or j, and if there is more of the same, look for the far right, you can, set index.
  • And then summed to
  • sum.get(n) - sum.get(index + 1) - pos * (n - index - 1) + (index + 1) * pos - sum.get(index + 1);
  • sum.get (n) - sum.get (index + 1) to calculate the current distance from the start point to the right side portion and
    • pos * (n - index - 1) minus the excess part, because prior to the start point and the distance is now required to the current point and the distance
  • (Index + 1) * pos - start to the left portion of the current point sum.get (index + 1) Here, index + 1 th current point distance minus the distance index + 1 and the starting point, namely a left portion and distance.

Method Two:

    • Processing prefix:
      prefixSum1 array a prefix and recording, namely:. PrefixSum1 [i] = a [0] + a [. 1] + .. + a [i]
      prefixSum2 prefixSum1 prefix and an array of records, prefixSum2 is the i-th point before the cost to the i-th point and.
    • Processing Suffix:
      prefixSum1 array of records and a suffix, namely:. PrefixSum1 [I] = a [n--. 1] + a [2-n-] + .. + a [I]
      prefixSum2 prefixSum1 suffix array and recorded, prefixSum2 i.e. i is a point after the cost to the i-th point and.
      public class Solution {
          /**
           * @param grid: a 2D grid
           * @return: An integer
           */
         public int shortestDistance(int[][] grid) {
              // Write your code here
              int n = grid.length;
              if (n == 0)
                  return -1;
      
              int m = grid[0].length;
              if (m == 0)
                  return -1;
      
              List<Integer> sumx = new ArrayList<Integer>();
              List<Integer> sumy = new ArrayList<Integer>();
              List<Integer> x = new ArrayList<Integer>();
              List<Integer> y = new ArrayList<Integer>();
      
              int result = Integer.MAX_VALUE;
              for (int i = 0; i < n; ++i)
                  for (int j = 0; j < m; ++j)
                      if (grid[i][j] == 1) {
                          x.add(i);
                          y.add(j);
                      }
              
              Collections.sort(x);
              Collections.sort(y);
      
              int total = x.size();
      
              sumx.add(0);
              sumy.add(0);
              for (int i = 1; i <= total; ++i) {
                  sumx.add(sumx.get(i-1) + x.get(i-1));
                  sumy.add(sumy.get(i-1) + y.get(i-1));
              }
      
              for (int i = 0; i < n; ++i)
                  for (int j = 0; j < m; ++j)
                      if (grid[i][j] == 0) {
                          int cost_x = get_cost(x, sumx, i, total);
                          int cost_y = get_cost(y, sumy, j, total);
                          if (cost_x + cost_y < result)
                              result = cost_x + cost_y;
                      }
      
              return result;
          }
      
          public int get_cost(List<Integer> x, List<Integer> sum, int pos, int n) {
              if (n == 0)
                  return 0;
              if (x.get(0) > pos)
                  return sum.get(n) - pos * n;
      
              int l = 0, r = n - 1;
              while (l + 1 < r) {
                  int mid = l + (r - l) / 2;
                  if (x.get(mid) <= pos)
                      l = mid;
                  else
                      r = mid - 1;
              }
              
              int index = 0;
              if (x.get(r) <= pos)
                  index = r;
              else
                  index = l;
              return sum.get(n) - sum.get(index + 1) - pos * (n - index - 1) + 
                     (index + 1) * pos - sum.get(index + 1);
          }
      }
      

        

Guess you like

Origin www.cnblogs.com/FLAGyuri/p/12078555.html