给出一个长度为 n 的数组 arr,在数组中找到一个长度 >= k 的区间,这个 区间中所有数字的和最小,返回这个最小值。
输入: 第一行 n, k。(1 <= n < 100000),第二行 n 个整数表示 arr[i](0 <= |arr[i]| <= 1000)。
输出:一个数,表示区间和的最小值。
样例输入
6 4
1 2 3 4 5 6
样例输出:
10 (1 + 2 + 3 + 4)
样例输入:
5 3
-2 1 -1 -1 -1
样例输出
-4 (全部加起来)
这道题有点类似 "最大和子数组"问题。这里用一个一维数组,dp[i] 表示以 arr 数组的 i 位置为结尾的所有区间的最小和。
状态转移方程为:dp[i] = min(dp[i - 1] + arr[i], sum[i - k + 1, i])
sum[i - k + 1, i] 是 [i - k + 1, i] 的闭区间内,所有值的和,当然需要判断一下 i - k + 1 和 0 的关系。
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n), dp(n, 0), presum(n + 1, 0);
for (int i = 0; i < n; ++i) {
cin >> a[i];
presum[i + 1] = a[i] + presum[i];
}
dp[0] = a[0];
int res = INT_MAX;
for (int i = 1; i < n; ++i) {
dp[i] = min(dp[i - 1] + a[i], presum[i + 1] - presum[max(0, i + 1 - k)]);
if(i >= k - 1)
res = min(res, dp[i]);
}
cout << res << endl;
}
值得注意的是,不用 presum 的方式,而是用 accumulate 的话,会超时。

336

被折叠的 条评论
为什么被折叠?



