【算法小总结】最大连续子序列和最大连续子矩阵的关系与实现
求最大子矩阵和是DP中的一类题目,今天我们就来讲一下一维(序列)与二维(矩阵)最大和
一.求最大连续子序列和
只需定义sum,扫一遍,sum为负时sum=0,具体见代码
#include<cstdio> #include<algorithm> using namespace std; const int N=1000; int x,sum,n,maxn; int main() { while(scanf("%d",&n),n) { sum=0,maxn=-0x3f3f3f3f; for(int i=1;i<=n;++i) { scanf("%d",&x); sum+=x; if(sum<0) sum=0; maxn=max(maxn,sum); } printf("%d\n",maxn); } }
例:
input
8
1 -3 -5 2 6 -1 4 9
output
20
二.求最大子矩阵和
这时需要将矩阵压缩成一维,然后套用一维的方法来做,首先定义a[i][j],表示第j列前i行数的和,
然后枚举i与j,表示从第i行到第j行的矩阵和最大值,最后在这些最大值中的最大值为所要的答案
举个例子:
1 -1 2
4 9 15
-7 1 10
第一次取
1 -1 2,对这一维数组求一次最大连续和,得到2,更新最大值为2
第二次取
1 -1 2
4 9 15,
(对列求和)求和得到
5 8 17,对这一维数组求最大连续和,得到30,更新最大值为30
第三次取
1 -1 2
4 9 15
-7 1 10
求和得到
-2 9 27,对这一维数组求最大连续和,得到36,更新最大值为36
第四次取
4 9 15,对这一维数组求最大连续和,得到28,更新最大值为36
第五次取
4 9 15
-7 1 10
求和得到
-3 10 25,对这一维数组求最大连续和,得到35,更新最大值为36
第六次取
-7 1 10,对这一维数组求最大连续和,得到11,更新最大值为36
所以最后得到答案为36,详情见代码
//求最大子矩阵和 //记录列和或者行和 //将二维转化为一维,按一维的求法求 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,a[150][150],sum,x,sum1[150];//a[i][j]记录了第j列前i行数相加得到的和 int get_max_sum()//获得最大连续序列和 { int maxsum=0,ret=-0x3f3f3f3f; for(int i=1;i<=n;++i) { maxsum+=sum1[i]; if(maxsum<0) maxsum=0; ret=max(ret,maxsum); } return ret; } int main() { while(scanf("%d",&n)==1) { for(int i=1;i<=n;++i)for(int j=1;j<=n;++j) { scanf("%d",&x); a[i][j]=a[i-1][j]+x; } sum=-0x3f3f3f3f; for(int i=1;i<=n;++i)for(int j=i;j<=n;++j) { for(int k=1;k<=n;++k) { sum1[k]=a[j][k]-a[i-1][k];//求在k列从i~j的和 } sum=max(sum,get_max_sum());//更新每次求矩阵和的最大值 } printf("%d\n",sum); } }
一直地一直地往前走