Minimum Total Distance Traveled

Hard
Watch on YouTube ↗

Solution

/***************Recursive + Memoization***************** */
class Solution {
    Long dp[][];
    // m, n = m*n
    public long minimumTotalDistance(List<Integer> robot, int[][] factory) {
        dp = new Long[robot.size()][factory.length];
        // sort
        Collections.sort(robot);
        Arrays.sort(factory, (a,b)->a[0]-b[0]);
        return helper(robot, factory, 0, 0);
    }

    long helper(List<Integer> robot, int[][] factory, int rindex, int findex) {
        // base case
        if(rindex==robot.size())
            return 0;
        if(findex==factory.length)
            return Long.MAX_VALUE;

        if(dp[rindex][findex]!=null)
            return dp[rindex][findex];
        
        // skip factory
        long skip = helper(robot, factory, rindex, findex+1);

        // take current factory
        long dist = 0;
        long ans = Long.MAX_VALUE;
        for(int k=0; k<factory[findex][1] && rindex+k<robot.size(); k++) {
            dist += Math.abs(robot.get(rindex+k)-factory[findex][0]);
            long next = helper(robot, factory, rindex+k+1, findex+1);
            if(next < Long.MAX_VALUE)
                ans = Math.min(ans, dist+next);
        }

        return dp[rindex][findex] = Math.min(skip, ans);
    }
}


/****************Iterative DP Solution***************** */
class Solution {

public long minimumTotalDistance(List<Integer> robot, int[][] factory) {
    Collections.sort(robot);                          
    Arrays.sort(factory, (a, b) -> a[0] - b[0]);     

    long[][] dp = new long[robot.size() + 1][factory.length + 1];

    for (int ri = 0; ri <= robot.size(); ri++)
        Arrays.fill(dp[ri], Long.MAX_VALUE);

    for (int fi = 0; fi <= factory.length; fi++)
        dp[robot.size()][fi] = 0;

    for (int ri = robot.size() - 1; ri >= 0; ri--) {
        for (int fi = factory.length - 1; fi >= 0; fi--) {

            long skip = dp[ri][fi + 1];

            long dist = 0;
            long ans = Long.MAX_VALUE;
            for (int k = 0; k < factory[fi][1] && ri + k < robot.size(); k++) {
                dist += Math.abs(robot.get(ri + k) - factory[fi][0]);
                long next = dp[ri + k + 1][fi + 1];
                if (next < Long.MAX_VALUE)
                    ans = Math.min(ans, dist + next);
            }

            dp[ri][fi] = Math.min(skip, ans);
        }
    }

    return dp[0][0];
}

    
}