AI 刷题 2. 徒步旅行中的补给问题题解 | 豆包MarsCode AI刷题

78 阅读2分钟

问题描述

小R正在计划一次从地点A到地点B的徒步旅行,总路程需要 N 天。为了在旅途中保持充足的能量,小R每天必须消耗1份食物。幸运的是,小R在路途中每天都会经过一个补给站,可以购买食物进行补充。然而,每个补给站的食物每份的价格可能不同,并且小R最多只能同时携带 K 份食物。

现在,小R希望在保证每天都有食物的前提下,以最小的花费完成这次徒步旅行。你能帮助小R计算出最低的花费是多少吗?

题解

public static int solution(int n, int k, int[] data) {
        // Edit your code here
        int length = data.length;
        int[] dp = new int[length];
        dp[0] = data[0];
        for (int i = 1; i < length; i++) {
            dp[i] = dp[i - 1] + data[i];
            for (int j = i - 1; j >= i - k + 1 && j >= 0; j--) {
                dp[i] = Math.min(dp[i], dp[i - 1] + data[j]);
            }
        }
        return dp[length - 1];
    }

思路解析

问题的目标是解决小R在途经补给站时,如何以最小花费完成旅程的问题。这里的关键在于动态规划方法的应用。代码中的核心思想是:

  1. 动态规划状态定义

    • dp[i] 表示从第 0 天开始到第 i 天,小R所需要的最小花费。
  2. 状态转移方程

    • 初始状态:dp[0] = data[0],即第 0 天的食物价格为唯一花费。
    • 递推关系:dp[i] = min(dp[i], dp[i - 1] + data[j]),在从前面 K 天中选择某一天补给,尝试以最优价格更新当天的总花费。
  3. 限制条件

    • 小R每天需要 1 份食物,因此每天都需要至少购买 1 份。
    • 小R最多可以携带 K 份食物,因此每次补给最多只能覆盖接下来的 K 天需求。

代码通过一个双层循环来实现:

  • 外层循环遍历每天的状态。
  • 内层循环从第 i-1 天开始向前最多回溯到 i-K+1 天,用来计算从某一天补给到第 i 天的最小花费。

解题步骤

  1. 初始化

    • 创建一个数组 dp,用于存储每天的最小花费。
    • 设置第一天的花费为 dp[0] = data[0]
  2. 遍历每一天

    • 对于第 i 天:

      • 初始将其花费设置为前一天的花费加当天的补给站价格:dp[i] = dp[i-1] + data[i]
      • 使用内层循环检查从第 i-1 天往前最多 K 天的补给方案,计算出更优的总花费。
      • 更新 dp[i]
  3. 返回结果

    • 返回 dp[length - 1],即到达最后一天的最小花费。

时间复杂度

时间复杂度为 O(N * K)