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

138 阅读3分钟

问题描述

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

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

测试样例

样例1:输入:n=5,k=2,data =[12, 3, 3, 2] 输出:9
样例2:输入:n=6,k=3,data=[4, 1, 5, 21, 3] 输出:9
样例3:输入:n=4,k=1,data =[3, 2, 41] 输出:10

题意分析

根据题面和样例分析题意

  1. 初始持有的食物为0,每天食物数减1;同时说明进入下一天时,食物数量可以为0
  2. 在一个补给站可以购买多份食物,否则题目中的食物数量限制是不可能达到的

代码

使用的是贪心策略,先把代码贴在这里,后面解释思路

public static int solution(int n, int k, int[] data) {
    int cost = 0;
    int f = 0;
    for (int i = 0; i < n; i++) {
        int j;
        for (j = i + 1; j < n; j++) {// 找到下一个比当前补给点更好的补给点
            if (data[j] <= data[i])
                break;
        }
        if (j - i <= f) {// 补给足够走到下一个补给点,不买
            f--;
            continue;
        }
        // 补给不够走到下一个好补给点
        if (j - i <= k) {
            cost += data[i] * (j - i - f);
            i = j - 1;
            f = 0;
        } else {
            cost += data[i] * (k - f);
            f = k - 1;
        }
    }//end for
        return cost;
   }

思路

主要考虑贪心

  • 找到下一个更便宜的补给点(称“好补给点”),则在当前站到下一个好补给点间,尽可能多地购买当前站的食物,会使费用最小
  • 因此需要找到下一个好补给点的位置

考虑

  • a.携带限制,当前补给站不一定能直接走到下一个好补给站
  • b.不能买了k份补给后直接跳转到k天后,可能会导致遇到高费用补给站(相对中间的路)而贪心失败

因此必须动态补充补给

思考过程

  • 如果背包足够,就直接买足够的补给,跳到下一个好补给点
  • 如果背包不够,第一想法肯定是找次优的点进行补给,但是这样就得递归寻找(次优的也不一定能找到),还得排序……还不一定对!
  • 第二个想法是动规,用一个数组存储状态,但是想了半天想不明白,每个站可以购买的容量是可以变化的,从1~k穷举显然不是个好办法
  • 最后就是这种,每走一步都试图找到下一个好补给点,看能不能走到,不能走到就补给

这里如何避免考虑b的情况?
首先不是一次性消耗所有补给进行滑动,而是每走一步判断一次是否需要补给
回归贪心,由于检测的是最近的更便宜站点,因此有
需要在该点补给==该点补给在到达好补给点之前是最好的选择==不会出错

感觉写得有点冗余了,总之就是一步一步进行贪心

其实我也不是很确定对不对……只能说过oj了,如果有错误之处欢迎讨论