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}