#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int solution(int n, int k, std::vector<int> data) {
// Edit your code here
std::vector<std::vector<int>> dp(n,std::vector<int>(k,INT_MAX));
for(int j = 0; j < k; j++){
dp[0][j] = data[0]*(j+1);
}
for(int i = 1; i < n; i++){
for(int j = 0; j < k; j++){
// 尝试从i - 1天的合适状态转移过来取最小值
if (j < k - 1) {
dp[i][j] = std::min(dp[i][j], dp[i - 1][j + 1]);
}
for(int x = 1; j - x + 1 >= 0; x++){
dp[i][j] = std::min(dp[i][j], dp[i-1][j - x + 1] + data[i] * x);
}
}
}
return dp[n-1] [0];
}
int main() {
// Add your test cases here
std::cout << (solution(5, 2, {1, 2, 3, 3, 2}) == 9) << std::endl;
return 0;
}
- 首先定义了一个二维的
std::vector
类型的 dp
,其大小为 n
行 k
列,并且将所有元素初始化为 INT_MAX
。这一步是为了在后续的状态转移过程中方便取最小值操作,因为初始时除了特定情况外,其他状态都视为未确定的极大值。 - 然后通过一个循环初始化
dp[0][j]
的值为 data[0]*(j + 1)
。这里的逻辑是在第一天时,对于不同剩余食物份数 j
的情况,计算其花费。假设第一天购买 j + 1
份食物,那么花费就是当天食物价格 data[0]
乘以购买的份数,这样就完成了第一天所有可能状态的初始化。
- 外层有两层嵌套
for
循环,外层循环遍历天数 i
(从 1
开始到 n - 1
),内层循环遍历资源状态 j
(从 0
到 k - 1
)。 - 在内层循环中,首先有一个
if
语句:if (j < k - 1)
。这里的目的是尝试从 i - 1
天的某个相关状态转移过来取最小值。当 j < k - 1
时,考虑从 dp[i - 1][j + 1]
转移过来,因为这表示前一天剩余食物份数多一份的情况,可能会影响到当前天的最小花费决策。这里需要注意的是,直接取最小值时,由于 dp[i][j]
初始为 INT_MAX
,所以要谨慎考虑 dp[i - 1][j + 1]
的值是否合法(不是 INT_MAX
),不过在当前代码中没有进行这个判断,这可能会导致一些潜在的错误结果被更新进去。 - 接着是一个
for
循环:for(int x = 1; j - x + 1 >= 0; x++)
。这个循环的目的是考虑在当前站点购买不同份数 x
的食物来更新当前状态 dp[i][j]
。循环条件 j - x + 1 >= 0
是为了确保在访问 dp[i - 1][j - x + 1]
时不会越界,它表示前一天剩余食物份数在减去购买的份数 x
后仍然在合法范围内。在循环体中,通过 dp[i][j] = std::min(dp[i][j], dp[i - 1][j - x + 1] + data[i] * x)
来更新当前状态的最小花费。这里计算的是在前一天剩余 j - x + 1
份食物的基础上,购买 x
份食物(花费 data[i] * x
)后的总花费,并与当前 dp[i][j]
的值取最小值,以得到当前状态的最小花费。