/*
 * File: min_cost_climbing_stairs_dp.rs
 * Created Time: 2023-07-09
 * Author: sjinzh (sjinzh@gmail.com)
 */

 use std::cmp;

/* 爬楼梯最小代价：动态规划 */
fn min_cost_climbing_stairs_dp(cost: &[i32]) -> i32 {
    let n = cost.len() - 1;
    if n == 1 || n == 2 { return cost[n]; }
    // 初始化 dp 表，用于存储子问题的解
    let mut dp = vec![-1; n + 1];
    // 初始状态：预设最小子问题的解
    dp[1] = cost[1];
    dp[2] = cost[2];
    // 状态转移：从较小子问题逐步求解较大子问题
    for i in 3..=n {
        dp[i] = cmp::min(dp[i - 1], dp[i - 2]) + cost[i];
    }
    dp[n]
}

/* 爬楼梯最小代价：空间优化后的动态规划 */
fn min_cost_climbing_stairs_dp_comp(cost: &[i32]) -> i32 {
    let n = cost.len() - 1;
    if n == 1 || n == 2 { return cost[n] };
    let (mut a, mut b) = (cost[1], cost[2]);
    for i in 3..=n {
        let tmp = b;
        b = cmp::min(a, tmp) + cost[i];
        a = tmp;
    }
    b
}

/* Driver Code */
pub fn main() {
    let cost = [ 0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1 ];
    println!("输入楼梯的代价列表为 {:?}", &cost);

    let res = min_cost_climbing_stairs_dp(&cost);
    println!("爬完楼梯的最低代价为 {res}");

    let res = min_cost_climbing_stairs_dp_comp(&cost);
    println!("爬完楼梯的最低代价为 {res}");
}
