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

184 阅读5分钟

徒步旅行中的补给问题

  • 问题描述

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

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

简单一些的思想就是: 贪心算法,尽量拿价格小的

本题的要求是最小花费,每个补给站的价格不一样,所以我们直接寻找价格最低的补给站去购买尽可能多的食物,这个时候就不能从头开始找这个补给站,而是从重点向起点走,因为对于价格最低的商店我们买了他的食物之恶能在他的后面使用,就如同题目中给的样例一样,在2号补给站购买足以到终点的食物,然后找价格第二低的补给站购买足够的食物,直到走到起点

先对存放补给站信息的二维数组按照食物的价格从低到高排序,然后从价格最低的那个补给站购买足以到达终点的食物,同时将终点坐标设置为该补给站的坐标,这样从前往后遍历的同时判断补给站的坐标哦是否小于终点坐标,小于的话就执行上面的操作,大于就直接跳过

这里我们去询问一下 豆包AI 是怎么说的,看看是怎么样的

数据结构选择

使用动态规划(DP)来解决这个问题。动态规划的核心思想是将问题分解为子问题,并通过解决子问题来解决原问题。

算法步骤

  1. 定义状态

    • dp[i][j] 表示第 i天结束时携带 j 份食物的最小花费。
    • dp[0][0] 初始化为0,表示第0天没有食物,花费为0。
  2. 状态转移

    • 对于每一天 i,我们需要考虑在前一天结束时携带的食物数量 j,以及在第 i天购买的食物数量 buy

      dp[i + 1][new_j] = min(dp[i + 1][new_j], dp[i][j] + buy * data[i])

其中 new_j 是第 i + 1 天结束时携带的食物数量,计算公式为 new_j = j + buy - 1

  1. 边界条件

    如果 dp[i][j] 为 float('inf'),表示当前状态不可达,跳过。 必须保证每天至少有一份食物,即 j + buy >= 1。

  2. 最终结果

    • 返回 dp[n][0],表示第 n 天结束时携带0份食物的最小花费。

我个人的想法是:

遍历到后面的时候,前面的价格应该也是要算进来的,也就说走到这个地方的话,购买的东西应该是从该站点开始往前 k 个站点最小价格的那一个,因为最多只能携带 k 份食物,所以遍历到该站点的时候,拿前面的第k + 1 个站点就需要从我们要选的价格表之中删除掉

每次插入时都要快速的选取最小值,这就很容易想到用最小堆,这里用对有个问题就是删除的节点不一定是堆顶,因为不知道前面 k + 1站点价格大小,所以删除结果之恶能对列表删除节点,然后构建堆

总结一下

对于这类的题目,如果按照正常的思维去模拟的话是很难写出正确答案,如果找到了他的贪心点的话就可以轻松解决了,而且贪心的题目中往往都是要求出最小次数之类的答案,同时需要利用排序辅助计算

贪心算法的技巧

  1. 局部最优选择

    • 贪心算法的核心思想是每一步都选择当前最优的解,而不考虑未来的影响。因此,设计贪心算法时,首先要确定如何定义“局部最优”。
  2. 排序

    • 在很多贪心问题中,排序是一个关键步骤。通过排序,可以将问题转化为更容易处理的形式。例如,按某个属性(如价格、时间、权重等)对元素进行排序,然后依次选择最优的元素。
  3. 反例验证

    • 贪心算法的一个常见问题是它不一定能保证全局最优解。因此,在设计贪心策略时,需要通过反例验证来确保该策略在所有情况下都能得到正确的结果。

需要注意的地方

  1. 贪心选择性质

    • 贪心算法的前提是问题具有贪心选择性质,即通过局部最优选择可以得到全局最优解。如果问题不具备这种性质,贪心算法可能会失败。
  2. 最优子结构

    • 贪心算法通常要求问题具有最优子结构,即问题的最优解可以通过子问题的最优解构造出来。如果问题不具备最优子结构,贪心算法可能不适用。
  3. 边界条件

    • 在实现贪心算法时,边界条件和特殊情况的处理非常重要。例如,空集、单个元素、极端值等情况都需要仔细考虑。
  4. 复杂度分析

    • 贪心算法通常具有较低的时间复杂度,但有时需要进行排序等操作,这会增加算法的复杂度。因此,在设计贪心算法时,需要考虑算法的整体复杂度。
  5. 与其他算法的结合

    • 有时贪心算法可以与其他算法(如动态规划、回溯等)结合使用,以解决更复杂的问题。例如,先用贪心算法得到一个近似解,再用其他算法进行优化。