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

147 阅读3分钟

原题链接:徒步旅行中的补给问题 - MarsCode

问题描述

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

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


测试样例

样例1:

输入:n = 5 ,k = 2 ,data = [1, 2, 3, 3, 2]
输出:9

样例2:

输入:n = 6 ,k = 3 ,data = [4, 1, 5, 2, 1, 3]
输出:9

样例3:

输入:n = 4 ,k = 1 ,data = [3, 2, 4, 1]
输出:10

问题分析

本题是很有趣的一个题目,思考的关键就在于不能按照线性的方法逐步思考,而要转化为一个等价的形式。

如果顺着常规的思路考虑,思路应该是这样:每到一个补给站,就要考虑目前手中有多少个份食物、未来的补给站的价格和当前补给站价格比较,然后决定应该在当前补给站购买多少食物。

这个思路当然是正确的,但是想要实现并不容易。但是如果反过来想:只管往前走,发现食物不够的话,从“过去的补给站”中找最便宜的一个,“为目前一步”购买一份食物。根据规则,我们当然不可能拐回去购买,但是我们只是用这个方法来思考问题,实际上认为我们是“在当时购买”的就可以了。

这样的思路能不能解决这个问题呢?首先,最小花费的问题一定可以解决,因为总是从最便宜的地方购买,但是怎么解决“手中持有的食物不超过K”呢?假如说在若干步后,始终发现第x步的商店最为便宜,每次都从x处购买,但是我们实际上是在当时一次性购买的,这就导致了第x步持有超过k的食物。

一个显然的方法是:采用一个K大小的滑动窗口,只记录最近K步的价格,这样一个最低价格至多被购买K次。

但是又有问题:“一个最低价格地点至多被购买K次”和“最多持有K个食物”等价吗?乍一看是不等价的,例如,我手中已经有2份食物,又购买K份,这样手里有2+K件食物,这不是超过了吗。在我们的算法中,这种情况可能发生吗?注意我们的规则:发现食物不够的话,从“过去的补给站”中找最便宜的一个,“为目前一步”购买一份食物。,只有在不够的时候才购买,因此不会出现上述超出的情况。这个解释起来比较麻烦,可以尝试找几个例子来理解。

最后代码如下:

def solution(n, k, data):
    # Edit your code here
    price = []
    now_food = 0
    total = 0
    for i in data:
        price.append(i)
        if len(price) > k:
            price.pop(0)
        now_food -= 1
        if now_food<0:
            total += min(price)
            now_food += 1
    return total