最大子序列和的总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最大子序列和
第一种情况:可以一个不取
【问题描述】:最大子序列和也叫数列的连续最大和,顾名思义,就是在一个长度为n的数列{An}中,求i,j(1<=i<=j<=n),使得数列{An}中,第i个元素到第j个元素之间,所有元素的和最大。例如:-2, 11, -4, 13, -5, -2时答案为20(11 -4 13)
解法一穷举法:以前我想出了一种算法,具体做法是:取出所给序列的所有子序列求和,共分n组,第一组长度为1,有n个;第二组长度为2, 有n-1个;……,最后一组,长度为n,只有一个。比较这n(n+1)/2个序列的和,再将每组的最大值比较,从而得到最大值以及其上下标。
a1 a2 a n-1 a n
a1+a2 a2+a3 a n-1+a n
a1+a2+a3 a2+a3+a4 ......
...... ......
a1+a2......+a n-1 a2+a3......+a n
a1+a2......+a n-1 +a n
此算法比较直接,也容易写出代码,但其时间开销为O(n2),空间开销为O(n),效率不高。
解法二:动态规划求解,
1
2
F[i]:表示以元素i结尾的连续最大子序列的和
那么对于第i个元素来说,要形成连续的最大子序列,只和相邻的前一个元素有关。因为可以不取,所以如果元素a[i]连接到以元素i-1结尾的最大连续子序列f[i-1]后是负数(f[i-1]+a[i]<0);则宁可不取,这样最大连续子序列和为0。
动态方程:
f[i]:=max{0,f[I-1]+a[i]} (边界条件:f[0]=0;)
3、代码1:
for I:=1 to n do
if (f[I-1]+a[i])>0 then f[i]:=f[I-1]+a[i] else f[i]:=0;
max:=-maxlongint;
for i:=1 to n do if f[i]>max then max:=f[i];
程序代码二:迭代进行
best:=-maxlongint;
temp:=0;
for i:=1 to n do
begin
temp:=temp+a[i]);
if temp>best then best:=temp;
if temp<0 then temp:=0;
end;
注意:加粗的循环体部分的顺序万万不可颠倒!
第二种情况:一定要取一个。
1、解法一:动态规划求解,
2
3
F[i]:表示以元素i结尾的至少要取一个的连续最大子序列的和
那么对于第i个元素来说,有两种选择:
选择一:因至少要选一个,所以可单独选a[i],此时和为a[i];
选择二:把a[i]连接到第i-1个元素结尾的最大连续子序列后。此时和为f[i-1]+a[i];
两种情况选较大者。
所以动态方程:
f[i]:=max{a[i],f[I-1]+a[i]} (边界条件:f[1]=a[1];)
4、代码:
F[1]:=a[1];
for I:=2 to n do
if (f[I-1]+a[i])>a[i] then f[i]:=f[I-1]+a[i] else f[i]:=a[i]; max:=-maxlongint;
for i:=1 to n do if f[i]>max then max:=f[i];
第三种情况:至少要取两个。
1、解法一:动态规划求解,
选择一:取长度为2:9-2=7;
选择二:把元素a[4]连接到元素a[3]结尾的后面。F[3]+a[4]=13-2
两者最较大者。
3、动态规划方程为:
F[i]:表示以元素i结尾的至少要取两个的连续最大子序列的和
那么对于第i个元素来说,有两种选择:
选择一:因至少要选两个,所以和为a[i-1]+a[i];
选择二:把a[i]连接到a[i-1]元素结尾的长度至少为2的最大连续子序列后。此时和为f[i-1]+a[i];
两种情况选较大者。
所以动态方程:
f[i]:=max{a[i-1]+a[i],f[I-1]+a[i]}(i>=3)
(边界条件:f[1]=a[1];f[2]=a[1]+a[2])
5、代码:
F[1]:=a[1]; f[2]:=a[1]+a[2];
for I:=3 to n do
if (f[I-1]+a[i])>a[i-1]+a[i] then f[i]:=f[I-1]+a[i]
else f[i]:=a[i-1]+a[i];
max:=-maxlongint;
for i:=2 to n do if f[i]>max then max:=f[i];
其它情况:
如2014年衢州市竞赛的转型,把相应的内容扩展到矩阵中而已。
5、求M子段和的最值。
问题描述:在一个长度为n的数列{An}中,求m个连续子序列,使得这m个连续子序列的和最大,且m个子序列无公共元素。特别地,若一子段的数全为负,则这个子段的和为0。(若两子段x[i..j]与y[i’..j’]不相交,则他们的关系是I<=j
输入:
第一行:n, m(1<=n<=100 1<=m<=10,m<=n) n表示数列中有多少数。
第二行:n个数每个数的绝对值<=1000
Sample Input
5 2
-5 9 -5 11 20