7-2 最大子段和(运用动态规划)

7-2 最大子段和(题目)

摘要:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0
要求算法的时间复杂度为O(n)

首先,我们注意题目的两个关键点
1.连续的子段序列
2.特殊情况:当所有给出的整数都为负数的时候,定义子段和为0
3.算法实现复杂度为O(n)

解题思路

运用了动态规划,其中复习动态规划的两个基本性质,最优子结构重复子问题

输入格式

输入有两行
第一行是n值(1<=n<=10000);
第二行是n个整数

输出格式

输出最大子段和

输入案例

6
-2 11 -4 13 -5 -2

输出案例

20

具体代码

#include 
using namespace std;
#define MAXSIZE 1000
int main() {
	int num;
	cin >> num;
	int Array[MAXSIZE] = { 0 };//初始化Array数组
	//在这里的思路最重要的就是确定动态规划的顺序,在这里我们首先确定Record数组里面的i的含义,
	//在这里即为以i结尾的最大字段和,然后初始化第一个元素(因为已经已知)
	//所以就是我们确定顺序为从左到右,而且当i个元素为负数的时候,考虑前面的Record为整数就相加,
	//如果第i个元素为正数的时候,我们考虑前面的Record[i-1]是否为正数,如果为正整数就相加,如果为负数就Record[i]赋值为Array[i]
	int Record[MAXSIZE] = { 0 };// Record[i]:以第i个数结尾的最大子段和
	int flag = 0;// 记录负数的个数的 
	for (int i = 0; i < num; i++) {
		cin >> Array[i];//输入数组的数值
		if (Array[i] < 0) {
			flag++;
		}//统计数组的负数个数
	}

	if (flag == num) {
		cout << 0;
	}//当所给的整数均为负数时,定义子段和为0。
	else {
		Record[0] = Array[0];//初始化从第一个元素到第一个元素结束时候
		for (int i = 1; i < num; i++) {
			if (Record[i - 1] <= 0) Record[i] = Array[i];
			else Record[i] = Record[i - 1] + Array[i];
		}
		int max = Record[0];
		for (int i = 0; i < num; i++) {
			if (max < Record[i]) {
				max = Record[i];
			}
		}//选择最大的max,遍历寻找最大值
		cout << max;
	}
}

递归表达式(还没写学会怎么写)(见谅)
R e c o r d [ i ] = { R e c o r d [ i − 1 ] + A r r a y [ i ]    i f   A r r a y [ i ] > 0   & &   R e c o r d [ i − 1 ] > = 0 R e c o r d [ i − 1 ] + A r r a y [ i ]     i f   R e c o r d [ i ] > 0   & & A r r a y [ i ] < 0   A r r a y [ i ]   i f   R e c o r d [ i − 1 ]   < 0   & &   A r r a y [ i ] > 0 Record[i]=\Bigg\{ \frac{ Record[i-1]+Array[i] \ \ if\ Array[i]>0 \ \&\& \ Record[i-1]>=0}{Record[i-1]+Array[i] \ \ \ if\ Record[i]>0 \ \& \& Array[i]<0 } \ Array[i]\ if \ Record[i-1]\ <0 \ \& \& \ Array[i]>0 Record[i]={Record[i1]+Array[i]   if Record[i]>0 &&Array[i]<0Record[i1]+Array[i]  if Array[i]>0 && Record[i1]>=0 Array[i] if Record[i1] <0 && Array[i]>0

重要思想

在这里的思路最重要的就是确定动态规划的顺序,在这里我们首先确定Record数组里面的i的含义,
在这里即为以i结尾的最大字段和,然后初始化第一个元素(因为已经已知),不难推出第一个元素和从左到右的关系
所以就是我们确定顺序为从左到右,而且当i个元素为负数的时候,考虑前面的Record为整数就相加,
如果第i个元素为正数的时候,我们考虑前面的Record[i-1]是否为正数,如果为正数相加,如果Record[i]为负数,Record[i]赋值为Array[i](因为Array[i]为正数)只有这样就能够确保数值最大。

你可能感兴趣的:(c++)