|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +# 2463. Minimum Total Distance Traveled |
| 4 | +# Hard |
| 5 | +# https://leetcode.com/problems/minimum-total-distance-traveled |
| 6 | + |
| 7 | +=begin |
| 8 | +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] = [positionj, limitj] indicates that positionj is the position of the jth factory and that the jth factory can repair at most limitj robots. |
| 9 | +The positions of each robot are unique. The positions of each factory are also unique. Note that a robot can be in the same position as a factory initially. |
| 10 | +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. |
| 11 | +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. |
| 12 | +Return the minimum total distance traveled by all the robots. The test cases are generated such that all the robots can be repaired. |
| 13 | +
|
| 14 | +Note that |
| 15 | +* All robots move at the same speed. |
| 16 | +* If two robots move in the same direction, they will never collide. |
| 17 | +* If two robots move in opposite directions and they meet at some point, they do not collide. They cross each other. |
| 18 | +* If a robot passes by a factory that reached its limits, it crosses it as if it does not exist. |
| 19 | +* If the robot moved from a position x to a position y, the distance it moved is |y - x|. |
| 20 | +
|
| 21 | +Example 1: |
| 22 | +Input: robot = [0,4,6], factory = [[2,2],[6,2]] |
| 23 | +Output: 4 |
| 24 | +Explanation: As shown in the figure: |
| 25 | +- The first robot at position 0 moves in the positive direction. It will be repaired at the first factory. |
| 26 | +- The second robot at position 4 moves in the negative direction. It will be repaired at the first factory. |
| 27 | +- The third robot at position 6 will be repaired at the second factory. It does not need to move. |
| 28 | +The limit of the first factory is 2, and it fixed 2 robots. |
| 29 | +The limit of the second factory is 2, and it fixed 1 robot. |
| 30 | +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. |
| 31 | +
|
| 32 | +Example 2: |
| 33 | +Input: robot = [1,-1], factory = [[-2,1],[2,1]] |
| 34 | +Output: 2 |
| 35 | +Explanation: As shown in the figure: |
| 36 | +- The first robot at position 1 moves in the positive direction. It will be repaired at the second factory. |
| 37 | +- The second robot at position -1 moves in the negative direction. It will be repaired at the first factory. |
| 38 | +The limit of the first factory is 1, and it fixed 1 robot. |
| 39 | +The limit of the second factory is 1, and it fixed 1 robot. |
| 40 | +The total distance is |2 - 1| + |(-2) - (-1)| = 2. It can be shown that we cannot achieve a better total distance than 2. |
| 41 | +
|
| 42 | +Constraints: |
| 43 | +* 1 <= robot.length, factory.length <= 100 |
| 44 | +* factory[j].length == 2 |
| 45 | +* -109 <= robot[i], positionj <= 109 |
| 46 | +* 0 <= limitj <= robot.length |
| 47 | +* The input will be generated such that it is always possible to repair every robot. |
| 48 | +=end |
| 49 | + |
| 50 | +# @param {Integer[]} robot |
| 51 | +# @param {Integer[][]} factory |
| 52 | +# @return {Integer} |
| 53 | +def minimum_total_distance(robot, factory) |
| 54 | + robot.sort! |
| 55 | + factory.sort! |
| 56 | + |
| 57 | + m, n = robot.length, factory.length |
| 58 | + dp = Array.new(m + 1) { Array.new(n + 1, 0) } |
| 59 | + m.times { |i| dp[i][n] = Float::INFINITY } |
| 60 | + |
| 61 | + (n - 1).downto(0) do |j| |
| 62 | + prefix = 0 |
| 63 | + qq = [[m, 0]] |
| 64 | + |
| 65 | + (m - 1).downto(0) do |i| |
| 66 | + prefix += (robot[i] - factory[j][0]).abs |
| 67 | + |
| 68 | + qq.shift if qq[0][0] > i + factory[j][1] |
| 69 | + |
| 70 | + while !qq.empty? && qq[-1][1] >= dp[i][j + 1] - prefix |
| 71 | + qq.pop |
| 72 | + end |
| 73 | + |
| 74 | + qq.push([i, dp[i][j + 1] - prefix]) |
| 75 | + dp[i][j] = qq[0][1] + prefix |
| 76 | + end |
| 77 | + end |
| 78 | + |
| 79 | + dp[0][0] |
| 80 | +end |
| 81 | + |
| 82 | +# **************** # |
| 83 | +# TEST # |
| 84 | +# **************** # |
| 85 | + |
| 86 | +require "test/unit" |
| 87 | +class Test_minimum_total_distance < Test::Unit::TestCase |
| 88 | + def test_ |
| 89 | + assert_equal 4, minimum_total_distance([0, 4, 6], [[2, 2], [6, 2]]) |
| 90 | + assert_equal 2, minimum_total_distance([1, -1], [[-2, 1], [2, 1]]) |
| 91 | + end |
| 92 | +end |
0 commit comments