问题描述
小R正在计划一次从地点A到地点B的徒步旅行,总路程需要 N 天。为了在旅途中保持充足的能量,小R每天必须消耗1份食物。幸运的是,小R在路途中每天都会经过一个补给站,可以先购买完食物后再消耗今天的1份食物。然而,每个补给站的食物每份的价格可能不同,并且小R在购买完食物后最多只能同时携带 K 份食物。
现在,小R希望在保证每天食物消耗的前提下,以最小的花费完成这次徒步旅行。你能帮助小R计算出最低的花费是多少吗?
**输入 **
n总路程需要的天数k小R最多能同时携带食物的份数data[i]第i天补给站每份食物的价格
**输出 **
- 返回完成这次徒步旅行的最小花费
**约束条件 **
1<n,k<10001<data[i]<10000
测试样例
样例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
function solution(n, k, data) {
let len = data.length
let dp = new Array(len)
console.log(dp);
dp[0] = data[0];
//
for (let i = 1; i < len; i++) {
debugger
// dp[i] 表示在第 i 天结束时的最小花费
// i i-1 data[i] dp[i - 1]
// 1 0 + 1 1 初始值 1
// 2 1 + 2 2 3 (data[1] + dp[i - 1]) 2 + 1(上次值)
// 3 2 + 3 3 6 (data[2] + dp[i - 1]) 3 + 3(上次值)
// 4 3 + 3 4 9 (data[3] + dp[i - 1]) 3 + 6(上次值)
// 5 4 + 2 5 11 (data[3] + dp[i - 1]) 2 + 9(上次值)
console.log(dp)
// 表示当前天的花费加上前一天的累计花费
dp[i] = dp[i - 1] + data[i];
// console.log('i', i,dp[i - 1] ,i-1, data[i],dp[i - 1] + data[i],dp,);
// j 初始化为 i - 1,表示从当前天的前一天开始。
// 循环从当前天的前一天开始,到当前天与 k 的差值(即 j >= i - k + 1)为止。
// 循环结束后,dp[i] 表示在第 i 天结束时的最小花费。
for (let j = i - 1; j >= i - k + 1 && j >= 0; j--) {
dp[i] = Math.min(dp[i], dp[i - 1] + data[j]);
}
}
// console.log(dp);
return dp[len - 1];
}
function main() {
// Add your test cases here
console.log('minCost:', solution(5, 2, [1, 2, 3, 3, 2])); // 输出最小花费
// console.log('minCost:', solution(6, 3, [4, 1, 5, 2, 1, 3])); // 输出最小花费
// console.log('minCost:', solution(4, 1, [3, 2, 4, 1])); // 输出最小花费
}
main()
通过动态规划的方法,计算出一个新的数组 new_dp,其中每个元素 new_dp[j] 表示在某种条件下的最优解。
动态规划的核心思想是通过子问题的解来构建原问题的解,从而避免重复计算,提高效率。
function solution(n, k, data) {
// 创建一个大小为 k + 10 的整数数组 dp。
let dp = new Array(k + 1).fill(Infinity);
// 初始化 dp 数组的前 k 个元素 并且大于0
for (let i = 1; i <= k; i++) {
// i = 1 data[0] 1 dp[i] = 1* 1
// i = 2 data[0] 1 dp[i] = 2* 1
dp[i] = i * data[0];
}
console.log(dp);
dp[k + 1] = Infinity;
console.log(dp);
// 外层循环遍历 data 数组的每个元素(从第 1 个到第 n-1 个)。
for (let i = 1; i < n; i++) {
// 创建一个新数组 new_dp,用于存储计算结果。
let new_dp = new Array(k + 1).fill(Infinity);
console.log('new_dp',new_dp);
new_dp[k + 1] = Infinity;
// 内层循环更新 new_dp 数组,计算每个状态的最小值
for (let j = 1; j <= k; j++) {
// 初始化 new_dp[j] 为无穷大 当前值
new_dp[j] = Infinity;
// 对于每个 j,遍历从 1 到 j + 1 的所有值 w
for (let w = 1; w <= j + 1; w++) {
// 找到 new_dp[j] 的最小值
// 其中 dp[w] 是前一个状态的值,
// (j - w + 1) * data[i] 是当前状态的增量
new_dp[j] = Math.min(new_dp[j], dp[w] + (j - w + 1) * data[i]);
}
}
dp = new_dp;
}
return dp[1];
}
function main() {
// Add your test cases here
console.log('minCost:', solution(5, 2, [1, 2, 3, 3, 2])); // 输出最小花费
console.log('minCost:', solution(6, 3, [4, 1, 5, 2, 1, 3])); // 输出最小花费
console.log('minCost:', solution(4, 1, [3, 2, 4, 1])); // 输出最小花费
}
main();