Skip to content

Commit

Permalink
Add problem 1928: Minimum Cost to Reach Destination in Time
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Sep 1, 2024
1 parent 84887f4 commit c4b5fe0
Show file tree
Hide file tree
Showing 3 changed files with 829 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,7 @@ pub mod problem_1922_count_good_numbers;
pub mod problem_1925_count_square_sum_triples;
pub mod problem_1926_nearest_exit_from_entrance_in_maze;
pub mod problem_1927_sum_game;
pub mod problem_1928_minimum_cost_to_reach_destination_in_time;
pub mod problem_1929_concatenation_of_array;
pub mod problem_1930_unique_length_3_palindromic_subsequences;
pub mod problem_1932_merge_bsts_to_create_single_bst;
Expand Down
129 changes: 129 additions & 0 deletions src/problem_1928_minimum_cost_to_reach_destination_in_time/dijkstra.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::cmp::Ordering;
use std::collections::BinaryHeap;

struct Item {
cost: u32,
countdown: u16,
node: u16,
}

impl PartialEq for Item {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}

impl Eq for Item {}

impl PartialOrd for Item {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Item {
fn cmp(&self, other: &Self) -> Ordering {
other.cost.cmp(&self.cost)
}
}

impl Solution {
pub fn min_cost(max_time: i32, edges: Vec<Vec<i32>>, passing_fees: Vec<i32>) -> i32 {
let max_time = max_time as u16;
let n = passing_fees.len();
let mut graph = vec![Vec::new(); n].into_boxed_slice();

for edge in edges {
let [from, to, time] = <[_; 3]>::map(edge.try_into().ok().unwrap(), |x| x as u16);

graph[usize::from(from)].push((to, time));
graph[usize::from(to)].push((from, time));
}

let mut queue = BinaryHeap::new();
let mut countdowns = vec![0; n].into_boxed_slice();

let mut item = Item {
cost: passing_fees[n - 1] as _,
countdown: max_time,
node: n as u16 - 1,
};

loop {
let countdown = &mut countdowns[usize::from(item.node)];

if *countdown < item.countdown {
*countdown = item.countdown;

for &(neighbor, time) in &graph[usize::from(item.node)] {
if let Some(candidate_countdown) = item.countdown.checked_sub(time) {
queue.push(Item {
cost: item.cost + passing_fees[usize::from(neighbor)] as u32,
countdown: candidate_countdown,
node: neighbor,
});
}
}
}

if let Some(next) = queue.pop() {
if next.node == 0 {
return next.cost as _;
}

item = next;
} else {
return -1;
}
}
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn min_cost(max_time: i32, edges: Vec<Vec<i32>>, passing_fees: Vec<i32>) -> i32 {
Self::min_cost(max_time, edges, passing_fees)
}
}

#[cfg(test)]
mod tests {
use super::Item;

#[test]
fn test_item_partial_eq() {
assert!(
Item {
cost: 2,
countdown: 5,
node: 7,
} == Item {
cost: 2,
countdown: 11,
node: 13,
}
);

assert!(
Item {
cost: 2,
countdown: 5,
node: 7,
} != Item {
cost: 3,
countdown: 5,
node: 7,
}
);
}

#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
Loading

0 comments on commit c4b5fe0

Please sign in to comment.