Skip to content

Commit 9b63699

Browse files
committed
Add problem 3186: Maximum Total Damage With Spell Casting
1 parent 2f5e2b0 commit 9b63699

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,6 +2126,7 @@ pub mod problem_3178_find_the_child_who_has_the_ball_after_k_seconds;
21262126
pub mod problem_3179_find_the_n_th_value_after_k_seconds;
21272127
pub mod problem_3184_count_pairs_that_form_a_complete_day_i;
21282128
pub mod problem_3185_count_pairs_that_form_a_complete_day_ii;
2129+
pub mod problem_3186_maximum_total_damage_with_spell_casting;
21292130
pub mod problem_3350_adjacent_increasing_subarrays_detection_ii;
21302131

21312132
#[cfg(test)]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
pub struct Solution;
2+
3+
// ------------------------------------------------------ snip ------------------------------------------------------ //
4+
5+
impl Solution {
6+
fn iter_groups(powers: &[u32], mut f: impl FnMut(u32, u64)) {
7+
let mut prev_power = 0_u32;
8+
let mut prev_power_sum = 0_u64;
9+
10+
for &power in powers {
11+
if power == prev_power {
12+
prev_power_sum += u64::from(power);
13+
} else {
14+
f(prev_power, prev_power_sum);
15+
16+
prev_power = power;
17+
prev_power_sum = u64::from(power);
18+
}
19+
}
20+
21+
f(prev_power, prev_power_sum);
22+
}
23+
24+
pub fn maximum_total_damage(power: Vec<i32>) -> i64 {
25+
let mut power = power.into_iter().map(i32::cast_unsigned).collect::<Vec<_>>();
26+
27+
power.sort_unstable();
28+
29+
let mut power_queue = [0_u32; 4];
30+
let mut damage_queue = [0_u64; 4];
31+
let mut cursor = 0;
32+
33+
Self::iter_groups(&power, |power, damage| {
34+
let diff = power.wrapping_sub(power_queue[cursor & 3]);
35+
36+
let offset = if diff < 3 {
37+
if diff == 1 && power.wrapping_sub(power_queue[(cursor + 3) & 3]) == 2 {
38+
2
39+
} else {
40+
3
41+
}
42+
} else {
43+
0
44+
};
45+
46+
let damage = damage_queue[cursor & 3].max(damage_queue[(cursor + offset) & 3] + damage);
47+
48+
cursor += 1;
49+
50+
power_queue[cursor & 3] = power;
51+
damage_queue[cursor & 3] = damage;
52+
});
53+
54+
damage_queue[cursor & 3].cast_signed()
55+
}
56+
}
57+
58+
// ------------------------------------------------------ snip ------------------------------------------------------ //
59+
60+
impl super::Solution for Solution {
61+
fn maximum_total_damage(power: Vec<i32>) -> i64 {
62+
Self::maximum_total_damage(power)
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
#[test]
69+
fn test_solution() {
70+
super::super::tests::run::<super::Solution>();
71+
}
72+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
pub mod dynamic_programming;
2+
3+
pub trait Solution {
4+
fn maximum_total_damage(power: Vec<i32>) -> i64;
5+
}
6+
7+
#[cfg(test)]
8+
mod tests {
9+
use super::Solution;
10+
11+
pub fn run<S: Solution>() {
12+
let test_cases = [
13+
(&[1, 1, 3, 4] as &[_], 6),
14+
(&[7, 1, 6, 6], 13),
15+
(&[5, 9, 2, 10, 2, 7, 10, 9, 3, 8], 31),
16+
];
17+
18+
for (power, expected) in test_cases {
19+
assert_eq!(S::maximum_total_damage(power.to_vec()), expected);
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)