7-1 最大子列和问题 (20分)

7-1 最大子列和问题 (20分)

给定\(K\)个整数组成的序列\({N_1, N_2, ..., N_K​}\),“连续子列”被定义为\({ N_i, N_{i+1}, ..., N_j}\),其中\(1≤i≤j≤K\)。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:与样例等价,测试基本正确性;
数据2:102个随机整数;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;

输入格式:

输入第1行给出正整数\(K (≤100000)\);第2行给出\(K\)个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2

输出样例:

20

思路

这是一道动态规划的题目。
先来个dp数组,是一维的还是二维的?
首先,不读完整个序列,无法确定连续最大子列。

  1. 尝试递归
    在读入第i个数,就确定了,直到i的连续最大子列,和也知道。
    那么读入第i+1个数。既然是最大,那么负数一定要排除。所以第i个数若是负数(情况1),此时必定不是最大子列的元素。
    第i个数若是正数,也不一定是最大子列的元素,因为可能,最大子列吸收它的代价太高。
    看第i+1个数,(情况1),如果能够补偿i的损失。
    (情况2),能够弥补吸收的代价。
    失败。
  2. 尝试递推
    这里的底层元素,显然就是每一个数本身。
    性质分类就是 + - 。
    如果i以后的数和为正,那么最大子列会吸收后续所有
    最大连续子列

9:15 2019/1/23 第二天思考。
dp数组应该是一维的。
对dp[i]先做初始化,在开头遇到的负数,其dp都为0
遇到第一个正数,及之后的所有数,dp为其本身。

/*这是主要方程,但不是全部*/
dp[i] = dp[i+1]+a[i];

10:34 2019/1/23 成功AC,对状态转移方程做了详细的定义。
分析了4种情况。我的想法是让人“未卜先知”,或者说是看到未来,所以是从最后一位数的dp来思考的。dp记录的是最大连续子列吸收该数的后果。要做到这一点,必须已经读入整个序列,从最后一个数开始考虑。因为随着后续数的不同,对某个数吸收与否的命运会改变。
如果已经知道吸收一个数的后果,就可以判断是否应该吸收了。
同时,吸收该数,希望吸收最小的坏后果,所以要对(a[i]>0 && dp[i+1]<0)特判,这种情况下,最优策略是仅仅吸收该整数本身。

AC代码

#include<bits/stdc++.h>
using namespace std;
int main(void){
	int n,i=0,sum=0;
	cin>>n;
	vector<int> dp(n),a(n);
	/*初始化dp数组*/
	bool flag = false;/*代表遇到正数以后*/
	while(cin>>a[i]){/*调试时,需要ctrl+z*/
		if(a[i]>0){
			flag =true;
			dp[i] = a[i];
		}
		else if(flag){
			dp[i] = a[i];
		}
		else{
			dp[i] = 0;
		}
		i++;
	} 
//	for(int i =0;i<n;i++){
//		cout<<a[i]<<endl;
//		cout<<dp[i]<<endl;
//	}
		
	/*成功读入*/
	/*状态转移方程*/
	for(int i=n-2;i>=0;i--){
		if(a[i]>0 && dp[i+1]<0){
			continue;
		}
		else
			dp[i] = dp[i+1] + a[i]; 
	}
	
	cout<<dp[0];
	return 0;
}

参考胡凡的书,这里对状态转移方程可以优化一波。

for(int i=n-2;i>=0;i--){
	dp[i] = max(a[i],dp[i+1] + a[i]); 
}

我的状态转移方程也是满足无后效性的。
从头开始的动态规划,就是定义了dp数组元素dp[i]为以a[i]结尾的连续子列最大和。
dp[i] = max(a[i],dp[i-1] + a[i]);
对最大和条件做了弱化,或者说是定义修改。
接着找出,这些和中值最大的那一个。

posted @ 2019-01-23 11:10  lingr7  阅读(448)  评论(2编辑  收藏  举报