分析:定义数组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; }