数组中长度至少为k的区间的最小和

给出一个长度为 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 的话,会超时。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值