一、徒步旅行中的补给问题 问题描述 小明想从A徒步到B,总路程需要N天,路程中为了确保安全,小明每天需要消耗1份食物。 从起点开始,小明每天都能遇到一个补给站,可以补充食物,不同补给站的食物价格可能不同。 小明最多能同时携带K份食物,请问小明若要安全完成徒步,最少要花多少钱?
输入格式 第一行为两个正整数N、K,代表总路程N天,最大负重K。 第二行为N个正整数,分别代表从第0天到第N-1天,每一个补给站的食物价格。
输出格式 输出一个正整数,代表最少花费金额。
输入样例
5 2
1 2 3 3 2
输出样例
9
说明:第0天买2份食物,花费2元;第一天买1份食物,花费2元;第三天买一份食物,花费3元;第四天买1份食物,花费2元;共花费9元。
数据范围 30%的数据,N <= 100,K <= N,0 <= B <= 100 80%的数据,N <= 10000, K <= 100, 0 <= B <= 100 100%的数据,N <= 1000000, K <= N,0 <= B <= 100 解题思路: 解题思路 问题理解:
小R每天需要消耗1份食物,且每天经过的补给站食物价格不同。 小R最多只能携带K份食物。 目标是找到在N天内完成旅行所需的最小花费。 数据结构选择:
使用动态规划(DP)来解决这个问题。 定义一个二维数组dp[i][l],表示在第i天结束时,携带l份食物的最小花费。 算法步骤:
初始化:dp[0][0] = 0,表示在第0天结束时,携带0份食物的花费为0。 状态转移: 对于每一天i,我们尝试从之前的某一天j转移过来。 计算在第i天购买食物的花费,并更新dp[i][l]。 返回结果:最终返回dp[n][0],即在第n天结束时,携带0份食物的最小花费。 具体步骤 初始化DP数组:
dp[0][0] = 0,其他dp[0][l](l > 0)为无穷大。 状态转移方程:
对于每一天i,遍历所有可能的食物携带量l(从0到K)。 对于每一个l,再遍历前一天的所有可能的食物携带量j(从0到K)。 如果l - j + 1在合理范围内(即0 <= l - j + 1 <= K),则更新dp[i][l]。 返回结果:
最终返回dp[n][0],即在第n天结束时,携带0份食物的最小花费。 最终代码: def solution(n, k, data): dp = [[float('inf')] * (k + 1) for _ in range(n + 1)] dp[0][0] = 0
for i in range(1, n + 1):
for l in range(k):
for j in range(k):
if l - j + 1 >= 0 and l - j + 1 <= k:
dp[i][l] = min(dp[i][l], dp[i - 1][j] + (l - j + 1) * data[i - 1])
# print(dp)
return dp[n][0]
if name == "main": print(solution(5, 2, [1, 2, 3, 3, 2]) == 9) print(solution(6, 3, [4, 1, 5, 2, 1, 3]) == 9) print(solution(4, 1, [3, 2, 4, 1]) == 10)