LeetCode-in-Java

3538. Merge Operations for Minimum Travel Time

Hard

You are given a straight road of length l km, an integer n, an integer k, and two integer arrays, position and time, each of length n.

The array position lists the positions (in km) of signs in strictly increasing order (with position[0] = 0 and position[n - 1] = l).

Each time[i] represents the time (in minutes) required to travel 1 km between position[i] and position[i + 1].

You must perform exactly k merge operations. In one merge, you can choose any two adjacent signs at indices i and i + 1 (with i > 0 and i + 1 < n) and:

Return the minimum total travel time (in minutes) to travel from 0 to l after exactly k merges.

Example 1:

Input: l = 10, n = 4, k = 1, position = [0,3,8,10], time = [5,8,3,6]

Output: 62

Explanation:

Segment Distance (km) Time per km (min) Segment Travel Time (min)
0 → 8 8 5 8 × 5 = 40
8 → 10 2 11 2 × 11 = 22

Example 2:

Input: l = 5, n = 5, k = 1, position = [0,1,2,3,5], time = [8,3,9,3,3]

Output: 34

Explanation:

Segment Distance (km) Time per km (min) Segment Travel Time (min)
0 → 2 2 8 2 × 8 = 16
2 → 3 1 12 1 × 12 = 12
3 → 5 2 3 2 × 3 = 6

Constraints:

Solution

@SuppressWarnings({"unused", "java:S1172"})
public class Solution {
    public int minTravelTime(int l, int n, int k, int[] position, int[] time) {
        int[][][] dp = new int[n][k + 1][k + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= k; j++) {
                for (int m = 0; m <= k; m++) {
                    dp[i][j][m] = Integer.MAX_VALUE;
                }
            }
        }
        dp[0][0][0] = 0;
        for (int i = 0; i < n - 1; i++) {
            int currTime = 0;
            for (int curr = 0; curr <= k && curr <= i; curr++) {
                currTime += time[i - curr];
                for (int used = 0; used <= k; used++) {
                    if (dp[i][curr][used] == Integer.MAX_VALUE) {
                        continue;
                    }
                    for (int next = 0; next <= k - used && next <= n - i - 2; next++) {
                        int nextI = i + next + 1;
                        dp[nextI][next][next + used] =
                                Math.min(
                                        dp[nextI][next][next + used],
                                        dp[i][curr][used]
                                                + (position[nextI] - position[i]) * currTime);
                    }
                }
            }
        }
        int ans = Integer.MAX_VALUE;
        for (int curr = 0; curr <= k; curr++) {
            ans = Math.min(ans, dp[n - 1][curr][k]);
        }
        return ans;
    }
}