Post Office Problem

Description

There are n houses on a line. Given an array A and A[i] represents the position of i-th house. Now you need to pick k position to build k post offices.

What is the minimum sum distance from these n houses to the nearest post office?

All positions are integers.

Example

Example 1:

Input: A = [1, 2, 3, 4, 5], k = 2
Output: 3
Explanation: Build post offices on position 2 and 4.

Example 2:

Input: A = [1, 2], k = 1
Output: 1
Explanation: Build post office on position 1 or 2.

Challenge

O ( n ^ 2 ) time

Ideas:

Linear dynamic programming (rather than a range of dynamic programming)

Can each house nearest post office, put  n a house divided into  k segments, and we have to decide is this  k segment are long. In order to help us deal with the sort of position before the house.

Setting f [i] [j] represents the j houses before the establishment of the optimal solution when i post office for this decision is that we need to state j before how many houses have shared the i-th post office, so it is:

f[i][j] = min{f[i - 1][j - x] + sumdis[j - x][j - 1]}
其中 sumdis[l][r] 表示下标范围为 [l, r] 的房子之间建立一个邮局, 这些房子与该邮局的最短距离
(注意f[i][j]中的j表示的第j栋房子从1计数, sumdis从0计数)

sumdis array can be realized out preprocessing, and specific nature of the algorithm that is related to the median sumdis [l] [r], which directly select r -. l + 1 houses the intermediate establish that a post office (if even-dong, optionally an intermediate of two), then the distance and houses the post office is the shortest.

As the boundary dp: f [i] [0] = 0, f [0] [j] = INF, and i> = j f when [i] [j] = 0

Further, such a state can be scrolled defined array optimization.

public class Solution {
    /**
     * @param A an integer array
     * @param k an integer
     * @return an integer
     */
    int[][] init(int[] A) {
        int n = A.length;
        int[][] dis = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; ++j) {
                int mid = (i + j) / 2;
                for (int k = i; k <= j; ++k)
                    dis[i][j] += Math.abs(A[k - 1] - A[mid - 1]);
            }
        }
        return dis;
    }

    public int postOffice(int[] A, int k) {
        // Write your code here
        int n = A.length;
        Arrays.sort(A);

        int[][] dis = init(A);
        int[][] dp = new int[n + 1][k + 1];
        if (n == 0 || k >= A.length)
            return 0;
        int ans = Integer.MAX_VALUE;
        for (int i = 0; i <= n; ++i) {
            dp[i][1] = dis[1][i];

        }

        for (int nk = 2; nk <= k; nk++) {
            for (int i = nk; i <= n; i++) {
                dp[i][nk] = Integer.MAX_VALUE;
                for (int j = 0; j < i; j++) {
                    if (dp[i][nk] == Integer.MAX_VALUE || dp[i][nk] > dp[j][nk - 1] + dis[j + 1][i])
                        dp[i][nk] = dp[j][nk - 1] + dis[j + 1][i];
                }
            }
        }
        return dp[n][k];
    }
}

  

Guess you like

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