现在的位置: 首页 > 综合 > 正文

hdu1003求最大子序列

2014年02月01日 ⁄ 综合 ⁄ 共 1173字 ⁄ 字号 评论关闭

分析:定义数组present[MAX]代表前i个数且包括第i个数的子序列的最大和,prior[MAX]表示前i个数最大子序列的和

所以有:present[i]=max(present[i-1]+s[i],s[i]);//前i-1个数包括第i-1个数的子序列最大和加上当前这个数构成的子序列,或者以当前这个数自成一个子序列,两者中选最大的。

                prior[i]=max(present[i],prior[i-1]);//前i个数的最大子序列和为:前i-1个数的最大子序列和或者前i个数且包括第i个数的最大子序列和。

继续分析发现每次求前i个最大子序列和都用不到0.....i-2的值,所以可以用滚动数组的思想节省内存

也就是:present=max(present+s[i],s[i]),prior=max(present,prior);每次计算前i个数时,present,prior就已经是前i-1的最大值,所以不需要present[i-1],prior[i-1];

对于输入的数s[i]也是每次都只需要用到s[i],对于s[0....i-1]不需要用到,所以在输入的时候计算就不需要用到s数组了。

此题还要记录选的子序列的第一个和最后一个,所以加个first,last辅助变量。

最终代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
using namespace std;

const int MAX=100001;
int present,prior,s,first,last,temp;

int main(){
	int t,n,num=1;
	cin>>t;
	while(t--){
		cin>>n;
 	    present=prior=-INF;
		for(int i=1;i<=n;++i){
			cin>>s;
			present+=s;
			if(s>present){present=s;temp=i;}//present=max(present+s,s)
			if(present>prior){prior=present;first=temp;last=i;}//prior=max(prior,present);
		}
		cout<<"Case "<<num++<<":\n";
		cout<<prior<<" "<<first<<" "<<last<<endl;
		if(t)cout<<endl;
	}
	return 0;
}

本题加强题:http://acm.hdu.edu.cn/showproblem.php?pid=1024

抱歉!评论已关闭.