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

62 阅读3分钟

问题描述

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

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

问题解题思路:
我们可以通过动态规划来解决这个问题。假设我们用一个数组arr[i]表示在第i天结束时,所需要的最小花费。我们的目标是计算出arr[N-1],即在完成所有N天的旅行时的最小花费。

状态转移方程:
  • 每天,arr[i]的值由前几天的状态推导而来。具体来说,在第i天,最小花费可以通过以下两种方式得到:

    • 从前一天购买足够的食物;
    • 从几天前购买一定数量的食物,并消耗这些食物直到第i天。

因此,状态转移方程可以表示为:

arr[i]=min(arr[j]+cost[j,i]),j∈[max(i−K+1,0),i]

其中,arr[j]是从第j天到第i天的最小花费,cost[j, i]是从第j天到第i天的购买食物费用。这里的关键在于,arr[j]已经代表了从第0天到第j天所需的最小花费,然后我们根据从ji的食物需求,选择最便宜的购买策略。

边界条件:
  • arr[0]表示第0天的最小花费,应该是购买第0天的食物的价格。
  • arr[i]表示第i天时的最小花费,需要从之前几天的状态中推导出来。
详细步骤:
  1. 初始化:首先,创建一个长度为N的数组arr来记录每一天结束时的最小花费。数组初始化为INT_MAX,表示初始状态下的花费是未知的,arr[0]初始化为第一天的食物价格。
  2. 迭代填充:从第1天开始,根据前几天的状态,填充arr[i]数组,计算每一天结束时的最小花费。
  3. 求解结果:最终,arr[N-1]就是完成N天旅程所需的最小花费。
代码解释:

在代码中,首先定义了一个arr数组,用于记录到每一天结束时的最小花费。然后通过双层循环,从前一天的状态推导出当前状态的最小花费。外层循环遍历每一天,内层循环从可能的前几天(最多K天)选择最小的花费。

优化与复杂度:

  • 由于我们需要对每一天进行处理,并且每一天最多需要检查前K天的花费,这样的时间复杂度为O(N * K),其中N是总天数,K是小R最多能够携带的食物数量。
  • 对于较大的NK,可能需要进一步的优化,例如使用单调队列来减少不必要的重复计算,但对于一般的输入规模,当前的方案是有效的。

给出代码:

#include <iostream>
#include <vector>
using namespace std;
int solution(int n, int k, std::vector<int> data) {
    // Edit your code here
    vector<int> arr(n+1,INT_MAX);
    arr[0]=data[0];
    for(int i=1;i<=n-1;i++)
    {
        int num=max(i-k+1,0);
        for(int j=num;j<=i;j++)
        {
            int a=min(data[i],data[j]);
            arr[i]=min(arr[i],arr[i-1]+data[j]);
        }
    }
  //  cout<<arr[5]<<endl;
    return arr[n-1];
}

int main() {
    // Add your test cases here

    std::cout << (solution(4, 1, {3, 2, 4, 1}) == 10) << std::endl;
    return 0;
}