package com.interview.algorithms.dp; /** * Created with IntelliJ IDEA. * User: stefanie * Date: 9/18/14 * Time: 11:22 AM * <p/> * N factories in one road, the distance between each of them to the west end of the road is D[N]. * Need pick M factories as supplier, to make the sum distance between the other factories to these M factories shortest. * <p/> * Solution: * Assumption: * 1. if need create 1 supplier between M-th and N-th factory, it should be the median factory to achieve shortest dist. * 2. assume A(i, j) is the shortest dist of factory(0-i) setup j supplier, * and B(m, n) is the shortest dist between M-th and N-th factory setup 1 supplier. * we could get the following formula: * A(i,j) = Min { A(t,j-1) + B(t+1,i) } 1<=t<i, t>=j-1 */ public class C12_21_PickFactory { public static int[] pick(int[] dist, int m) { int[][] pre = new int[dist.length][m + 1]; for (int p = 0; p < dist.length; p++) { pre[p][0] = distance(dist, 0, p); pre[p][1] = dist[p >> 1]; } for (int j = 2; j <= m; j++) { for (int i = 0; i < dist.length; i++) { if (i + 1 >= j){ //could get one more supplier int min = Integer.MAX_VALUE; //A(i,j) = Min { A(t,j-1) + B(t+1,i) } 1<=t<i, t>=j-1 for (int t = i - 1; t >= 0; t--) { if (t + 1 >= j - 1) { //could get one more supplier int curDis = pre[t][0] + distance(dist, t + 1, i); if (min > curDis) { min = curDis; for (int k = 1; k <= j - 1; k++) { pre[i][k] = pre[t][k]; //copy the old solution } pre[i][j] = dist[(t + 1 + i) >> 1]; } } } pre[i][0] = min; } } } return pre[dist.length - 1]; } /** * the shortest dist from mth - nth factories if set 1 supplier. * the supplier get shortest dist should be the the mid of the factories. * * @param dist * @param left * @param right * @return */ private static int distance(int[] dist, int left, int right) { int mid = (left + right) >> 1; int dis = 0; for (int i = left; i <= right; i++) { int dif = dist[i] - dist[mid]; dis += ((dif > 0) ? dif : -1 * dif); } return dis; } }