leetcode

Leetcode problem solutions
git clone https://git.sinitax.com/sinitax/leetcode
Log | Files | Refs | sfeed.txt

2463-minimum-total-distance-traveled.rs (5397B)


      1/// 2463. Minimum Total Distance Traveled (Hard)
      2///
      3/// There are some robots and factories on the X-axis. You are given an integer
      4/// array robot where robot[i] is the position of the ith robot. You are also
      5/// given a 2D integer array factory where factory[j] = [positionj, limitj]
      6/// indicates that positionj is the position of the jth factory and that the jth
      7/// factory can repair at most limitj robots.
      8///
      9/// The positions of each robot are *unique*. The positions of each factory are
     10/// also *unique*. Note that a robot can be *in the same position* as a factory
     11/// initially.
     12///
     13/// All the robots are initially broken; they keep moving in one direction. The
     14/// direction could be the negative or the positive direction of the X-axis.
     15/// When a robot reaches a factory that did not reach its limit, the factory
     16/// repairs the robot, and it stops moving.
     17///
     18/// *At any moment*, you can set the initial direction of moving for *some*
     19/// robot. Your target is to minimize the total distance traveled by all the
     20/// robots.
     21///
     22/// Return the minimum total distance traveled by all the robots. The test cases
     23/// are generated such that all the robots can be repaired.
     24///
     25/// *Note that*
     26///
     27///   * All robots move at the same speed.
     28///   * If two robots move in the same direction, they will never collide.
     29///   * If two robots move in opposite directions and they meet at some point,
     30///   they do not collide. They cross each other.
     31///   * If a robot passes by a factory that reached its limits, it crosses it as
     32///   if it does not exist.
     33///   * If the robot moved from a position x to a position y, the distance it
     34///   moved is |y - x|.
     35///
     36/// *Example 1:*
     37///
     38///   *Input:* robot = [0,4,6], factory = [[2,2],[6,2]]
     39///   *Output:* 4
     40///   *Explanation:* As shown in the figure:
     41///   - The first robot at position 0 moves in the positive direction. It will be
     42///     repaired at the first factory.
     43///   - The second robot at position 4 moves in the negative direction. It will be
     44///     repaired at the first factory.
     45///   - The third robot at position 6 will be repaired at the second factory. It
     46///     does not need to move.
     47///   The limit of the first factory is 2, and it fixed 2 robots.
     48///   The limit of the second factory is 2, and it fixed 1 robot.
     49///   The total distance is |2 - 0| + |2 - 4| + |6 - 6| = 4. It can be shown that
     50///   we cannot achieve a better total distance than 4.
     51///
     52/// *Example 2:*
     53///
     54///   *Input:* robot = [1,-1], factory = [[-2,1],[2,1]]
     55///   *Output:* 2
     56///   *Explanation:* As shown in the figure:
     57///   - The first robot at position 1 moves in the positive direction. It will be
     58///     repaired at the second factory.
     59///   - The second robot at position -1 moves in the negative direction. It will be
     60///     repaired at the first factory.
     61///   The limit of the first factory is 1, and it fixed 1 robot.
     62///   The limit of the second factory is 1, and it fixed 1 robot.
     63///   The total distance is |2 - 1| + |(-2) - (-1)| = 2. It can be shown that we
     64///   cannot achieve a better total distance than 2.
     65///
     66/// *Constraints:*
     67///
     68///   * 1 <= robot.length, factory.length <= 100
     69///   * factory[j].length == 2
     70///   * -109 <= robot[i], positionj <= 109
     71///   * 0 <= limitj <= robot.length
     72///   * The input will be generated such that it is always possible to repair
     73///   every robot.
     74///
     75use leetcode::*;
     76
     77struct Solution {}
     78
     79impl Solution {
     80    fn dp(
     81        robot: &Vec<i32>,
     82        factory: &Vec<Vec<i32>>,
     83        cache: &mut [i64],
     84        ri: usize,
     85        fi: usize,
     86    ) -> i64 {
     87        if ri >= robot.len() {
     88            return 0;
     89        }
     90
     91        if fi >= factory.len() {
     92            return i64::MAX;
     93        }
     94
     95        let cached = cache[ri * factory.len() + fi];
     96        if cached != -1 {
     97            return cached;
     98        }
     99        let mut answer = Self::dp(robot, factory, cache, ri, fi + 1);
    100        let mut dist = 0;
    101        for i in 0..factory[fi][1] {
    102            let rri = ri + i as usize;
    103            if rri >= robot.len() {
    104                break;
    105            }
    106            dist += (robot[rri] - factory[fi][0]).abs() as i64;
    107            // we skip the current factory entirely. it is never optimal for
    108            // non-consecutive robots to be assigned to the same factory (!)
    109            let res = Self::dp(robot, factory, cache, rri + 1, fi + 1);
    110            if res == i64::MAX {
    111                continue;
    112            }
    113            answer = std::cmp::min(answer, dist + res)
    114        }
    115        cache[ri * factory.len() + fi] = answer;
    116
    117        answer
    118    }
    119
    120    pub fn minimum_total_distance(mut robot: Vec<i32>, mut factory: Vec<Vec<i32>>) -> i64 {
    121        factory.sort_by(|a, b| a[0].cmp(&b[0]));
    122        robot.sort();
    123
    124        let mut cache: Box<[i64]> = vec![-1; factory.len() * robot.len()].into_boxed_slice();
    125        Self::dp(&robot, &factory, &mut cache, 0, 0)
    126    }
    127}
    128
    129pub fn main() {
    130    println!(
    131        "{:?}",
    132        Solution::minimum_total_distance(arg_into(1), arg_into(2))
    133    )
    134}
    135
    136#[cfg(test)]
    137mod tests {
    138    use crate::Solution;
    139    use leetcode::{vi, vvi};
    140
    141    #[test]
    142    fn test() {
    143        assert_eq!(
    144            Solution::minimum_total_distance(vi("[0,4,6]"), vvi("[[2,2],[6,2]]")),
    145            4
    146        );
    147        assert_eq!(
    148            Solution::minimum_total_distance(vi("[1,-1]"), vvi("[[-2,1],[2,1]]")),
    149            2
    150        );
    151    }
    152}