徒步旅行中的补给问题
小R正在计划一次从地点A到地点B的徒步旅行,总路程需要 N 天。为了在旅途中保持充足的能量,小R每天必须消耗1份食物。幸运的是,小R在路途中每天都会经过一个补给站,可以购买食物进行补充。然而,每个补给站的食物每份的价格可能不同,并且小R最多只能同时携带 K 份食物。
现在,小R希望在保证每天都有食物的前提下,以最小的花费完成这次徒步旅行。你能帮助小R计算出最低的花费是多少吗?
解答:
理解了第一题后这道题也就迎刃而解了, 这一题同样规定了最多只能携带K个食物, 但是补给点为每一天一个,与上一题类似, 只不过省去了距离dis的判断
c++
代码解读
复制代码
int solution(int n, int k, std::vector<int> data) {
vector<vector<int>> memo(n, vector<int>(k+1, -1));
auto dfs = [&](auto&& dfs, int i, int bag) -> int
{
if (i == n) {
return 0;
}
int& res = memo[i][bag];
if (res!=-1) {
return res;
}
int ans = 100000;
// 决定买多少份食物
int j = (bag == 0) ? 1 : 0; // bag == 0 时必须买
for (; j <= k - bag; ++j) {
int current_cost = j * data[i] + dfs(dfs, i + 1, bag + j - 1);
ans = min(ans, current_cost);
}
memo[i][bag] = ans;
return ans;
};
return dfs(dfs, 0, 0);
}
徒步旅行中的补给问题
补给站最优花费问题
小U计划进行一场从地点A到地点B的徒步旅行,旅行总共需要 M 天。为了在旅途中确保安全,小U每天都需要消耗一份食物。在路程中,小U会经过一些补给站,这些补给站分布在不同的天数上,且每个补给站的食物价格各不相同。
小U需要在这些补给站中购买食物,以确保每天都有足够的食物。现在她想知道,如何规划在不同补给站的购买策略,以使她能够花费最少的钱顺利完成这次旅行。
- M:总路程所需的天数。
- N:路上补给站的数量。
- p:每个补给站的描述,包含两个数字 A 和 B,表示第 A 天有一个补给站,并且该站每份食物的价格为 B 元。
保证第0天一定有一个补给站,并且补给站是按顺序出现的。
解:
这一题同样类似第一题,只不过没有了最大容量MAX_CAPACITY的限制
c++
代码解读
复制代码
int solution(int m, int n, std::vector<std::vector<int>> p) {
int food_index = 0;
p.push_back({m, 0});
std::vector<std::vector<int>> memo(n, std::vector<int>(m,-1));
auto dfs = [&](auto&& dfs, int i, int bag)->int
{
if(i==n)
return 0;
int& res = memo[i][bag];
if(res != -1)
return res;
int price = p[i][1];
int dis = p[i+1][0] - p[i][0];
int temp = 10000;
//不买
if(bag>=dis)
temp = std::min(temp, dfs(dfs, i+1, bag-dis));
//买
for(int buy = 1; buy<=m-p[i][0]; buy++)
{
if(buy + bag >= dis)
temp = std::min(temp, buy*price+dfs(dfs, i+1, bag+buy-dis));
}
res = temp;
return temp;
};
int ans = dfs(dfs, 0, 0);
return dfs(dfs, 0, 0);
}
题目要求我们计算一组观光景点的最高组合得分。每个景点都有一个评分,保存在数组 values 中。一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,即两者评分之和减去它们之间的距离。
我们需要找到一种方法,使得在所有可能的景点组合中,得分最高。
解题思路 理解公式:
组合得分公式为 values[i] + values[j] + i - j。 可以将其拆分为 (values[i] + i) + (values[j] - j)。 优化思路:
对于每个 j,我们只需要找到在 i < j 的情况下,使得 values[i] + i 最大的 i。 这样,我们可以通过一次遍历数组来计算每个 j 对应的最高得分。 算法步骤:
初始化一个变量 max_i_plus_value 来保存当前最大的 values[i] + i。 遍历数组 values,对于每个 j,计算 max_i_plus_value + values[j] - j,并更新最大得分。 同时更新 max_i_plus_value。 数据结构选择 使用一个变量 max_i_plus_value 来保存当前最大的 values[i] + i。 使用一个变量 max_score 来保存当前的最大得分。 复杂度分析 时间复杂度:O(n),因为我们只需要遍历数组一次。 空间复杂度:O(1),因为我们只使用了常数个额外变量
#include #include #include
int solution(std::vector values) { // write code here int mx = 0; for(int i = 0 ; i < values.size();i++){ for(int j = i + 1;j < values.size();j++){ mx = fmax(values[i] + values[j] + i - j,mx); } } return mx; // Placeholder return }
int main() { std::cout << (solution({8, 3, 5, 5, 6}) == 11) << std::endl; std::cout << (solution({10, 4, 8, 7}) == 16) << std::endl; std::cout << (solution({1, 2, 3, 4, 5}) == 8) << std::endl; return 0; }
完美偶数计数
问题描述
小C定义了一个“完美偶数”。一个正整数 xx 被认为是完美偶数需要满足以下两个条件:
xx 是偶数; xx 的值在区间 [l,r][l,r] 之间。 现在,小C有一个长度为 nn 的数组 aa,她想知道在这个数组中有多少个完美偶数。
测试样例 样例1:
输入:n = 5,l = 3,r = 8,a = [1, 2, 6, 8, 7] 输出:2
样例2:
输入:n = 4,l = 10,r = 20,a = [12, 15, 18, 9] 输出:2
样例3:
输入:n = 3,l = 1,r = 10,a = [2, 4, 6] 输出:3
解题思路: 问题理解 我们需要在一个数组 a 中找出满足以下两个条件的元素个数:
该元素是偶数。 该元素在区间 [l, r] 之间。
def is_even_number(a):
return a % 2 == 0
def solution(n, l, r, a): # 计算在范围 [l, r] 内的偶数个数 return sum(1 for i in a if is_even_number(i) and l <= i <= r)
if name == "main": a1 = [1, 2, 6, 8, 7] print(solution(5, 3, 8, a1) == 2) # 输出: True
a2 = [12, 15, 18, 9]
print(solution(4, 10, 20, a2) == 2) # 输出: True
a3 = [2, 4, 6]
print(solution(3, 1, 10, a3) == 3) # 输出: True