洛谷P1614 爱与愁的心痛(滑动窗口解法)

爱与愁的心痛

题目背景

(本道题目隐藏了两首歌名,找找看哪~~~)

《爱与愁的故事第一弹·heartache》第一章。

《我为歌狂》当中伍思凯神曲《舞月光》居然没赢给萨顶顶,爱与愁大神心痛啊~~~而且最近还有一些令人伤心的事情,都让人心痛(最近真的很烦哈)……

题目描述

最近有 n 个不爽的事,每句话都有一个正整数刺痛值(心理承受力极差)。爱与愁大神想知道连续 m 个刺痛值的和的最小值是多少,但是由于业务繁忙,爱与愁大神只好请你编个程序告诉他。

输入格式

第一行有两个用空格隔开的整数,分别代表 n 和 m。

第 2 到第 (n + 1) 行,每行一个整数,第 (i + 1) 行的整数 ai 代表第 i 件事的刺痛值 ai。

输出格式

输出一行一个整数,表示连续 m 个刺痛值的和的最小值是多少。

样例 #1

样例输入 #1

8 3
1
4
7
3
1
2
4
3

样例输出 #1

6

提示

数据规模与约定

  • 对于 30% 的数据,保证 n <=20
  • 对于 60% 的数据,保证 n <=100。
  • 对于 90% 的数据,保证 n <=10^3.
  • 对于 100% 的数据,保证 0<=m<=n<=3*10^3;1<=ai<=100

这题有什么思路?

这题拿到手我们就有一个极为暴力的思路,使用两层for循环遍历每一个m个数的组合,找出最小数,这样我们就可以直接解决问题了。但是,这种方法的时间复杂度为o(n^2),在数据量比较大的时候,我们对

元素操作的次数太多了,可能效率会非常低。这时候我们可以考虑使用滑动窗口的解法。

滑动窗口

所谓滑动窗口,顾名思义,他就是像一个滑动的窗口,来遍历数组,可以在一个for循环内完成两个for循环需要完成的事情。

我们可以先记录一下a[0]-a[m-1],这m个元素的和,然后将滑动窗口一个一个元素向后移,比较当前组合和最小的m个元素之和的大小,并且实时更新:

	//使用CurrentSum变量来储存当前m个数的和
	int CurrentSum = 0;
	//先计算前m个数的和
	for (int i = 0; i < m; i++) CurrentSum += a[i];
	//m个数的和的最小值
	int minSum = CurrentSum;
C++代码如下:
#include<vector>
#include<iostream>
using namespace std;
int main()
{
	//输入数据
	int n, m; cin >> n >> m;
	//定义a数组,存储n个数
	vector<int> a(n);
	for (int i = 0; i < n; i++) cin >> a[i];
	//使用CurrentSum变量来储存当前m个数的和
	int CurrentSum = 0;
	//先计算前m个数的和
	for (int i = 0; i < m; i++) CurrentSum += a[i];
	//m个数的和的最小值
	int minSum = CurrentSum;
	//从第m+1个数开始,滑动窗口开始移动
	for (int i = m; i < n; i++) {
		//滑动窗口加上现在这个元素,减去最后面那个元素
		CurrentSum += a[i] - a[i - m];
		//minSum取这些组合里面的最小值
		minSum = minSum > CurrentSum ? CurrentSum : minSum;
	}
	cout << minSum;
	return 0;
}

posted @ 2024-07-16 13:07  Tomorrowland_D  阅读(10)  评论(0编辑  收藏  举报