https://atcoder.jp/contests/abc266/tasks/abc266_d
各すぬけ君が現れる時刻に各穴での最大値を記憶していけばよいですね。
穴の数が固定なので、ここでは配列を使っています。
定数はこんな感じに定義します。
const M: usize = 5;
配列はこう初期化します。
let mut new_dp: [usize; M] = [0; M];
0がM個の配列です。Mが定数だからこうできるわけですね。
// Snuke Panic (1D) #![allow(non_snake_case)] use std::cmp::{min, max}; const M: usize = 5; //////////////////// library //////////////////// fn read<T: std::str::FromStr>() -> T { let mut line = String::new(); std::io::stdin().read_line(&mut line).ok(); line.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>().split_whitespace() .map(|e| e.parse().ok().unwrap()).collect() } //////////////////// process //////////////////// fn read_input() -> Vec<(usize, usize, usize)> { let N: usize = read(); (0..N).map(|_| read_vec()).map(|v| (v[0], v[1], v[2])). collect::<Vec<(usize, usize, usize)>>() } fn update(dp: [usize; M], T0: &usize, T: &usize, X: &usize, A: &usize) -> [usize; M] { let mut new_dp: [usize; M] = [0; M]; for i in 0..M { new_dp[i] = dp[i] } for from in 0..min(T0+1, M) { let dT = T - T0; let min_to = if from < dT { 0 } else { from - dT }; let max_to = if M - from <= dT { M - 1 } else { from + dT }; for to in min_to..(max_to+1) { if to == *X { new_dp[to] = max(dp[from] + A, new_dp[to]) } else { new_dp[to] = max(dp[from], new_dp[to]) } } } new_dp } fn f(v: Vec<(usize, usize, usize)>) -> usize { let mut dp: [usize; M] = [0; M]; dp = update(dp, &0, &v[0].0, &v[0].1, &v[0].2); for ((T0, _, _), (T, X, A)) in v.iter().zip(&v[1..]) { dp = update(dp, T0, T, X, A) } *dp.iter().max().unwrap() } fn main() { let v = read_input(); println!("{}", f(v)) }