LeetCode - 2463 Minimum Total Distance Traveled

LeetCode - 2463 Minimum Total Distance Traveled

LAVI

Hard

2463. Minimum Total Distance Traveled

題目

There are some robots and factories on the X-axis. You are given an integer array robot where robot[i] is the position of the ith robot. You are also given a 2D integer array factory where factory[j] = [position_j, limit_j] indicates that position_j is the position of the jth factory and that the factory can repair at most limit_j robots.

The positions of each robot are unique. The positions of each factory are unique. Note that a robot can be in the same position as a factory initially.

All the robots are initially broken; they keep moving in one direction. The direction could be the negative or the positive direction of the X-axis. When a robot reaches a factory that did not reach its limit, the factory repairs the robot, and it stops moving.

At any moment, you can set the initial direction of moving for some robot. Your target is to minimize the total distance traveled by all the robots.

Return the minimum total distance traveled by all the robots. The test cases are generated such that all the robots can be repaired.

Note that

  • All robots move at the same speed.
  • If two robots move in the same direction, they will never collide.
  • If two robots move in opposite directions and they meet at some point, they do not collide. They cross each other.
  • If a robot passes by a factory that reached its limits, it crosses it as if it does not exist.
  • If the robot moved from a position x to a position y, the distance it moved is |y - x|.

Example 1

Input: robot = [0,4,6], factory = [[2,2],[6,2]]
Output: 4
Explanation: As shown in the figure:

  • The first robot at position 0 moves in the positive direction. It will be repaired at the first factory.
  • The second robot at position 4 moves in the negative direction. It will be repaired at the first factory.
  • The third robot at position 6 will be repaired at the second factory. It does not need to move.
    The limit of the first factory is 2, and it fixed 2 robots.
    The limit of the second factory is 2, and it fixed 1 robot.
    The total distance is |2 - 0| + |2 - 4| + |6 - 6| = 4. It can be shown that we cannot achieve a better total distance than 4.

Example 2

Input: robot = [1,-1], factory = [[-2,1],[2,1]]
Output: 2
Explanation: As shown in the figure:

  • The first robot at position 1 moves in the positive direction. It will be repaired at the second factory.
  • The second robot at position -1 moves in the negative direction. It will be repaired at the first factory.
    The limit of the first factory is 1, and it fixed 1 robot.
    The limit of the second factory is 1, and it fixed 1 robot.
    The total distance is |2 - 1| + |(-2) - (-1)| = 2. It can be shown that we cannot achieve a better total distance than 2.

Constraints

  • 1 <= robot.length, factory.length <= 100
  • factory[j].length == 2
  • -10^9 <= robot[i], position_j <= 10^9
  • 0 <= limit_j <= robot.length
  • The input will be generated such that it is always possible to repair every robot.

解題思路

這題是經典區間分配 DP
最佳解一定可以做到不交叉分配,最佳解應該會是每個 factory 負責一段連續的 robots

  • 先將 robotfactory 都排序

    • 這樣才能保證後面 DP 做的是「前幾個 robot」配給「前幾間 factory」
  • DP 定義:

    • dp[i][j]:前 i 個 robots,使用前 j 間工廠修理的最小總距離
  • 初始化:

    • dp[0][j] = 0
    • 如果沒有 robot 要修,不管有幾間工廠,成本都是 0
    • 其他先設成很大的值 INF
  • j 輪表示正在考慮第 j 間工廠(實際 index 是 j - 1

    • pos:工廠位置
    • limit:工廠容量
  • 對於每個 dp[i][j]

    • 先考慮不使用第 j 間工廠修理任何 robot
      dp[i][j] = dp[i][j - 1]

    • 再考慮讓第 j 間工廠修理最後 k 個 robots

      • k 最多只能到 min(i, limit)
      • cost 表示把最後 k 個 robots 全部分給這間工廠的成本
      • dp[i - k][j - 1] 意思是前 i-k 個 robots 用前 j-1 間工廠搞定
      • 因此轉移為:
        dp[i][j] = min(dp[i][j], dp[i - k][j - 1] + cost)
  • 最後答案是:
    dp[n][m]

Solution Code

Time Complexity
O(n × m × limit)

Space Complexity
O(n × m)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public:
long long minimumTotalDistance(vector<int>& robot, vector<vector<int>>& factory) {
// 最佳解一定可以做到不交叉分配,最佳解應該會是每個 factory 負責一段連續的 robots
sort(robot.begin(), robot.end());
sort(factory.begin(), factory.end());

int n = robot.size();
int m = factory.size();
const long long INF = 1e18; // 不能直接用 LLONG_MAX 會爆掉

vector<vector<long long>> dp(n + 1, vector<long long>(m + 1, INF));
for(int j = 0; j <= m; ++j) dp[0][j] = 0; // 如果沒有 robot 要修,不管有幾間工廠,成本都是 0

// 第 j 輪表示我們正在考慮第 j 間工廠(實際 index 是 j-1)
for (int j = 1; j <= m; j++) {
int pos = factory[j - 1][0]; // pos:工廠位置
int limit = factory[j - 1][1]; // limit:工廠容量

for (int i = 1; i <= n; i++) { // 考慮「前 i 個 robots」的最優解
dp[i][j] = dp[i][j - 1]; // 不使用第 j 間工廠修理任何 robot

long long cost = 0;

// 讓第 j 間工廠修理最後 k 個 robots
for (int k = 1; k <= min(i, limit); k++) {
cost += abs((long long)robot[i - k] - pos); // 把最後 k 個 robots 全部分給這間工廠的成本累加起來
// dp[i - k][j - 1] 意思是前 i-k 個 robots 用前 j-1 間工廠搞定
// cost 意思是 最後 k 個 robots 給第 j 間工廠
dp[i][j] = min(dp[i][j], dp[i - k][j - 1] + cost);
}
}
}

return dp[n][m];
}
};
On this page
LeetCode - 2463 Minimum Total Distance Traveled