豆包2 徒步旅行中的补给问题

285 阅读3分钟

问题描述

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

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

算法使用

dfs

算法思路

  1. 初始化备忘录

    • 定义一个二维数组memo,其中memo[i][j]表示在第i天,携带j份食物时的最小花费。数组的大小为n x (k + 1),其中n是天数,k是最大携带食物量。
    • memo数组中的所有元素初始化为-1,表示尚未计算。
  2. 定义递归函数

    • 定义一个递归函数dfs,它接受当前天数i,当前携带的食物量cur,以及总天数n和最大携带食物量k作为参数,并返回从第i天开始到第n天的最小花费。
  3. 处理边界情况

    • 如果i等于n,即已经到达最后一天,返回0,因为不需要再购买食物。
    • 如果memo[i][cur]不等于-1,表示已经计算过这个状态,直接返回memo[i][cur]
  4. 计算最小花费

    • 初始化一个变量resInteger.MAX_VALUE,用于存储当前状态下的最小花费。
    • 遍历所有可能的购买食物量t,从1到k - cur(即最多可以购买的食物量),计算购买t份食物后的花费,并递归调用dfs函数计算后续天数的最小花费。
    • 如果当前携带的食物量cur不为0,可以选择不购买食物,直接进入下一天,并递归调用dfs函数计算后续天数的最小花费。
  5. 更新备忘录

    • 将计算得到的最小花费res存储到memo[i][cur]中。
  6. 返回结果

    • solution函数返回从第0天开始,携带0份食物时的最小花费,即dfs(data, k, 0, 0, n)

代码展示

import java.util.Arrays;

public class Main {
    private static int[][] memo;

    public static int solution(int n, int k, int[] data) {
        // Edit your code here
        memo = new int[n][k + 1];
        for (int i = 0; i < n; i++) {
            Arrays.fill(memo[i], -1);
        }
        return dfs(data, k, 0, 0, n);
    }

    public static int dfs(int[] data, int k, int i, int cur, int n) {
        if (i == n) {
            return 0;
        }
        if (memo[i][cur] != -1) {
            return memo[i][cur];
        }
        int res = Integer.MAX_VALUE;
        // 对于当前天, 可以啥也不干进入下一天, 可以购买若干粮食进入下一天
        for (int t = 1; t + cur <= k; t++) {
            res = Math.min(res, dfs(data, k, i + 1, cur + t - 1, n) + data[i] * t);
        }
        res = cur != 0 ? Math.min(res, dfs(data, k, i + 1, cur - 1, n)) : res;
        return memo[i][cur] = res;
    }

    public static void main(String[] args) {
        // Add your test cases here

        System.out.println(solution(5, 2, new int[] { 1, 2, 3, 3, 2 }));
    }
}