LeetCode 2463 - Minimum Total Distance Traveled
Here is a comprehensive, reference-quality solution guide for LeetCode 2463 - Minimum Total Distance Traveled following your formatting requirements.
Difficulty: 🔴 Hard
Topics: Array, Dynamic Programming, Sorting
Solution
Here is a comprehensive, reference-quality solution guide for LeetCode 2463 - Minimum Total Distance Traveled following your formatting requirements.
Problem Understanding
The problem gives us a set of robots on an X-axis, each at a unique position, and a set of factories, each at a unique position with a maximum capacity of robots it can repair. Robots are initially broken, and you can set their initial movement direction along the X-axis. When a robot reaches a factory that has not yet reached its repair limit, the robot is repaired and stops moving. The goal is to assign robots to factories and directions in a way that minimizes the total distance traveled by all robots.
The input consists of:
robot: an array of integers representing the positions of robots. Each position is unique.factory: a 2D array[[positionj, limitj]]representing factory positions and the maximum number of robots they can repair.
The output is a single integer representing the minimum total distance all robots travel to reach factories.
Constraints and Observations:
- The number of robots and factories is small (
<= 100), so algorithms with polynomial complexity in these dimensions are acceptable. - Robot and factory positions can be negative or positive and may be very large in magnitude (
-10^9to10^9). - It is guaranteed that all robots can be repaired, so we do not need to handle impossible scenarios.
- Robots can move past factories if the factory is at capacity.
- Robots can move in either direction along the X-axis; this allows flexibility in assignment.
Edge considerations include: robots starting at the same position as a factory, factories with zero capacity, and robots needing to move in opposite directions to minimize total distance.
Approaches
Brute-Force Approach:
A naive approach is to consider all permutations of robot assignments to factories. For each permutation, calculate the total distance while respecting the factory limits. This is guaranteed to give the correct answer because it explores all possibilities, but the complexity is factorial in the number of robots (O(n!)) and quickly becomes intractable for n = 100.
Optimal Approach - Dynamic Programming:
The key observation is that both robot and factory positions can be sorted along the X-axis, allowing a structured assignment from left to right. Once sorted, we can use dynamic programming to compute the minimum distance efficiently.
Define dp[i][j] as the minimum total distance to assign the first i robots to the first j factories. For each factory, you can assign k robots (up to the factory limit), and you update the dp value using the sum of distances for those k robots. This avoids exploring all permutations explicitly.
Why DP Works: Sorting ensures that assigning robots to factories in increasing order does not miss an optimal configuration. The problem reduces to combining subproblems of assigning subsets of robots to factories, which dynamic programming handles efficiently.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n!) | O(n!) | Explore all permutations of robot-factory assignments |
| Dynamic Programming | O(m * n^2) | O(m * n) | m = number of factories, n = number of robots; uses prefix sums for distance |
Algorithm Walkthrough
- Sort robots and factories by their positions. Sorting ensures that closer robots are considered for closer factories first.
- Initialize a DP table
dp[i][j]representing the minimum distance to assign the firstirobots using the firstjfactories. Initializedp[0][0] = 0(no robots assigned, zero distance). - Iterate over factories in sorted order. For each factory
j, consider assigningkrobots to it, where0 <= k <= limit[j]andk <= i(the remaining number of robots to assign). - Compute distance sums efficiently using prefix sums for robots' positions. The total distance for assigning
krobots to a factory is the sum of|robot[i] - factory[j].position|for the chosen robots. - Update DP state:
dp[i][j] = min(dp[i][j], dp[i-k][j-1] + distance_sum_for_k_robots)
6. The answer is dp[n][m] after filling the DP table, representing all robots assigned to all factories.
Why it works:
- Sorting guarantees that we always consider the closest robots for each factory first, avoiding suboptimal assignments.
- DP correctly combines subproblems of assigning subsets of robots to subsets of factories, maintaining the minimal total distance invariant.
- Prefix sums allow distance sums to be computed in
O(1)for any consecutive group of robots.
Python Solution
from typing import List
import sys
class Solution:
def minimumTotalDistance(self, robot: List[int], factory: List[List[int]]) -> int:
robot.sort()
factory.sort(key=lambda x: x[0])
n, m = len(robot), len(factory)
# dp[i][j] = min distance to assign first i robots to first j factories
dp = [[sys.maxsize] * (m + 1) for _ in range(n + 1)]
dp[0][0] = 0
for j in range(1, m + 1):
pos, limit = factory[j-1]
dp[0][j] = 0 # zero robots assigned
for i in range(1, n + 1):
# Assign 0 robots to current factory
dp[i][j] = dp[i][j-1]
dist_sum = 0
# Try assigning k robots to this factory
for k in range(1, min(limit, i) + 1):
dist_sum += abs(robot[i - k] - pos)
dp[i][j] = min(dp[i][j], dp[i - k][j - 1] + dist_sum)
return dp[n][m]
Explanation:
- Robots and factories are sorted to simplify distance minimization.
dp[i][j]stores the minimal distance for assigningirobots to the firstjfactories.- For each factory, we try assigning
krobots (up to its capacity) and update the DP using the previous state. dist_sumaccumulates the distances for the robots assigned to the current factory efficiently.
Go Solution
package main
import (
"math"
"sort"
)
func minimumTotalDistance(robot []int, factory [][]int) int64 {
sort.Ints(robot)
sort.Slice(factory, func(i, j int) bool { return factory[i][0] < factory[j][0] })
n, m := len(robot), len(factory)
dp := make([][]int64, n+1)
for i := range dp {
dp[i] = make([]int64, m+1)
for j := range dp[i] {
dp[i][j] = math.MaxInt64
}
}
dp[0][0] = 0
for j := 1; j <= m; j++ {
pos, limit := factory[j-1][0], factory[j-1][1]
dp[0][j] = 0
for i := 1; i <= n; i++ {
dp[i][j] = dp[i][j-1]
var distSum int64 = 0
for k := 1; k <= limit && k <= i; k++ {
distSum += int64(abs(robot[i-k] - pos))
if dp[i-k][j-1] != math.MaxInt64 {
dp[i][j] = min(dp[i][j], dp[i-k][j-1]+distSum)
}
}
}
}
return dp[n][m]
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func min(a, b int64) int64 {
if a < b {
return a
}
return b
}
Go-specific notes:
- Uses slices of
int64to handle large distance sums safely. - Sorting uses
sort.Slicewith a custom comparator for factories. - No special handling needed for empty slices as constraints guarantee at least one robot and one factory.
Worked Examples
Example 1:
Input: robot = [0,4,6], factory = [[2,2],[6,2]]
Step-by-step DP updates:
| i (robots) | j (factories) | Assigned robots to factory j | Distance sum | dp[i][j] |
|---|---|---|---|---|
| 1 | 1 | 1 robot (0) | 2-0 | |
| 2 | 1 | 2 robots (0,4) | 2-0 | |
| 3 | 2 | 1 robot (6) | 6-6 |
Final output: 4
**Example 2