一、徒步旅行中的补给问题
问题描述
小明想从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)
运行结果:

二、超市里的货物架调整
问题描述
在一个超市里,有一个包含 nn 个格子的货物架,每个格子中放有一种商品,商品用小写字母 a 到 z 表示。当顾客进入超市时,他们会依次从第一个格子查找到第 nn 个格子,寻找自己想要购买的商品。如果在某个格子中找到该商品,顾客就会购买它并离开;如果中途遇到一个空格子,或查找完所有格子还没有找到想要的商品,顾客也会离开。
作为超市管理员,你可以在顾客到来之前重新调整商品的顺序,以便尽可能多地出售商品。当第一个顾客进入后,商品位置不能再调整。你需要计算在最优调整下,最多可以卖出多少件商品。输入变量说明:
n:货物架的格子数m:顾客想要购买的商品种类数s:货物架上商品的初始顺序c:顾客想要购买的商品种类
测试样例
样例1:
输入:
n = 3 ,m = 4 ,s = "abc" ,c = "abcd"
输出:3
样例2:
输入:
n = 4 ,m = 2 ,s = "abbc" ,c = "bb"
输出:2
样例3:
输入:
n = 5 ,m = 4 ,s = "bcdea" ,c = "abcd"
输出:4
解题思路:
问题理解
你需要在顾客到来之前重新调整商品的顺序,以便尽可能多地出售商品。每个顾客只会购买他们想要的商品中的一种,并且一旦找到就会离开。因此,我们的目标是通过重新排列商品,使得尽可能多的顾客能够找到他们想要的商品。
数据结构选择
- 商品频率统计:首先,我们需要统计货架上每种商品的数量,以及顾客想要购买的每种商品的数量。
- 商品匹配:然后,我们需要计算在当前货架上,最多可以满足多少种顾客的需求。
算法步骤
-
统计商品频率:
- 遍历货架上的商品,统计每种商品的数量。
- 遍历顾客想要的商品,统计每种商品的需求数量。
-
计算最大匹配:
- 对于每种顾客想要的商品,计算货架上该商品的数量与顾客需求数量的最小值。
- 累加这些最小值,得到最多可以满足的顾客数量。
关键点
- 商品的顺序调整:虽然题目允许我们调整商品的顺序,但实际上我们只需要统计商品的数量,而不需要实际调整顺序。
- 商品的匹配:我们只需要计算每种商品的供需匹配情况,而不需要实际模拟顾客的购买过程。
最终代码:
#include <bits/stdc++.h>
using namespace std;
int solution(int n, int m, string s, string c) {
map<char , int> ps , pc;
for(auto it : s)
ps[it] ++;
for(auto it : c)
pc[it] ++;
int cnt = 0;
for(auto [k , v] : pc)
cnt += min(ps[k] , v);
return cnt;
}
int main() {
cout << (solution(3, 4, "abc", "abcd") == 3) << endl;
cout << (solution(4, 2, "abbc", "bb") == 2) << endl;
cout << (solution(5, 4, "bcdea", "abcd") == 4) << endl;
return 0;
}
运行结果:

三、观光景点组合得分问题
问题描述
小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。
一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。
小R想知道,在哪种情况下能够获得观光景点组合的最高得分。
测试样例
样例1:
输入:
values = [8, 3, 5, 5, 6]
输出:11
样例2:
输入:
values = [10, 4, 8, 7]
输出:16
样例3:
输入:
values = [1, 2, 3, 4, 5]
输出:8
解题思路:
问题理解
我们需要找到一对景点 (i, j) 使得 values[i] + values[j] + i - j 的值最大,其中 i < j。
数据结构选择
我们可以使用一个变量来记录当前的最大得分,并在遍历数组时更新这个变量。
算法步骤
-
初始化:
- 初始化一个变量
maxScore来记录当前的最大得分,初始值为 0。 - 初始化一个变量
maxValue来记录当前的最大values[i] + i,初始值为values[0] + 0。
- 初始化一个变量
-
遍历数组:
- 从第二个元素开始遍历数组。
- 对于每个元素
values[j],计算当前的得分values[i] + values[j] + i - j,其中i是之前遍历过的元素中values[i] + i最大的那个。 - 更新
maxScore为当前得分和maxScore中的较大值。 - 更新
maxValue为values[j] + j和maxValue中的较大值。
-
返回结果:
- 遍历结束后,
maxScore即为所求的最大得分。
- 遍历结束后,
最终代码:
#include <bits/stdc++.h>
using namespace std;
int solution(vector<int> values) {
if(values.size() == 1) return 0;
int maxv = 0 , res = 0;
for(int i = 0 ; i < values.size() ; i ++)
{
res = max(res , values[i] - i + maxv);
maxv = max(maxv , values[i] + i);
}
return res; // Placeholder return
}
int main() {
cout << (solution({8, 3, 5, 5, 6}) == 11) << endl;
cout << (solution({10, 4, 8, 7}) == 16) << endl;
cout << (solution({1, 2, 3, 4, 5}) == 8) << endl;
return 0;
}
运行结果:
