动态规划——最大连续子序列和

动态规划之——最大连续子序列和(C++实现)

最大连续子序列和,或称为“连续子序列的和的最大值”,是一种动态规划问题,下面来看问题描述

给定一个长度为n数字序列A1, A2, A3······An, 现要求求出一组(i,j),使得:Ai + ······ + Aj 的和最大,输出这个最大和

测试用样例见下

输入:

6
1 -3 5 8 -100 52
4
-2 85 -15 62
5
1 2 -5 6 -9 1

输出:

52
132
6

接下来开始讲解

用双重循环暴力枚举 i,j 靠谱吗?枚举(i,j)需要 O(n²) 的复杂度,计算 Ai + ······ + Aj 需要 O(n) 的复杂度,乘起来是立方阶 O(n³), 令人难以接受

暴力枚举 ,pass !

接下来考虑动态规划的做法,开一个dp数组,以dp[i]来表示以A[i]结尾的最大子序列和(注意是强制以A[i]结尾),那么答案显然就是max(dp[1], dp[2], ······ ,dp[n])了,可是能一目了然的看出来的貌似只有dp[1],它的值显然等于A[1],其他的又该怎么办呢?

在动态规划题目中,能用眼睛看出答案的部分往往是这个问题的边界 ,是状态转移方程的起点,这也是动态规划的妙处所在:以边界处渺小的信息量,通过状态转移方程,逐步推出整个问题的解

一旦确定了状态转移方程和边界,距离AC这道题目就不远了!

而状态转移方程是动态规划问题的绝对核心,类型繁多,甚至往往需要就题论题,掌握它可以说是任重而道远(博主在写这篇博文时也在全身心投入动态规划的学习)

然而本题的状态方程并不复杂,对于dp[i] (i >= 2) 来说,dp[i - 1]的正负直接决定了dp[i]的取值,若dp[i - 1]为正,那么dp[i]就等于A[i]本身加上dp[i - 1],若dp[i - 1]为负,那么dp[i]就等于A[i]本身

更简单的来说,dp[i] = max{ dp[i - 1] + A[i], A[i] }

有了边界和状态转移方程,接下来,上代码!

#include//使用万能头文件自然便捷,但为了照顾使用VS的小伙伴我也只好忍痛割爱
#include//实际上,VS也可以人工配置万能头文件,大家可以参考其他博主的教程,耀氏的教程近期也会做出来
using namespace std;
const int maxn = 10000 + 10;//"xxx + 10"中的"10"是为了避免数组越界,是很多选手共有的习惯
int arr[maxn], dp[maxn];//arr用于存放原序列,dp用于状态转移
int n;//原序列的长度
int main()
{
	ios::sync_with_stdio(false);//关闭与stdio的同步以加快输入输出速度

	while (cin >> n)
	{
		//初始化
		memset(arr, 0, sizeof(arr));
		for (int i = 1; i <= n; i++)
			cin >> arr[i];

		//处理边界
		//一切动态规划问题都需要处理边界,试想,若没有边界,状态又该从何处开始转移? 失去起点的状态方程又有何意义?
		//而落实到本题,不经过状态方程的处理就能够直接得到的"边界"只有
		dp[1] = arr[1];

		for (int i = 2; i <= n; i++)
			dp[i] = max(arr[i], arr[i] + dp[i - 1]);//状态转移方程,动态规划题目的绝对核心

		//虽然dp数组已经全部求解完毕,但我们仍无法确定dp数组中的最大值
		//此时我们可以充分调用库里的库函数max_element
		//max_element(arr + i, arr + j)返回x∈[i, j)区间上最大的arr[x]的地址,因此常搭配*(解引用符号)使用,以此来获得数组中指定区间上的最大值
		//对于自定义的数据类型,则需要重载 operator< 来告诉计算机如何比较自定义数据类型的大小
		//max和min总是同生共死,因此,与之相对的,存在min_element,用法与它完全相同
		//这两个函数的时间复杂度?当然是O(n)!因为对于一个无序数组,不可能存在不遍历它的各个元素就找到最大值的算法
		//大家可千万不要被某些博文中无脑声称的O(log(n))的复杂度迷惑了
		cout << *max_element(dp + 1, dp + n + 1) << endl; 
	}
	return 0;
}

好了,本篇关于最大连续子序列和问题的博文就到此结束了,这已经是本人所写的第二篇博客啦,第一篇博客中第一次收到评论和点赞,真是感动呢!

以后,我会更新更多学习路上所攻克的难题,让我们一起加油!如果需要提问或指正,欢迎在评论区留下你的足迹!我会在看到的第一时间回复!

最后,我是耀桑,期待你的关注

你可能感兴趣的:(算法,动态规划)