一维问题:nyoj 44 子串和
链接:click here
题目大意:给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。
思路:m是元素总个数,sum是第一个元素,将当前的第一个元素作为最大值max,之后依次输入,检查sum<0?是的话更新sum为当前输入值:否则累加,最后比较这样每次步骤的最大值。
代码:
#include <stdio.h> #include <math.h> #include <string.h> #include <iostream> #include <algorithm> int main() { int n,m,q,max,sum; scanf("%d",&n); while(n--) { max=0; scanf("%d",&m); scanf("%d",&sum); max=sum; while(m--) { scanf("%d",&q); if(sum<0) sum=q; else sum+=q; if(sum>max) max=sum; } printf("%d\n",max); } return 0; }二维问题:nyoj 104 最大和
链接:click here
题目大意:
给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。
例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩阵为:
9 2
-4 1
-1 8
其元素总和为15。
思路:
二维的问题,其实可以转化为一维的问题。
首先我们要注意到二维子矩阵在选取的时候是个矩阵,联系一个我们经常会用到的技巧:需要频繁计算一个数据任意一个区间的和的时候,我们会预先把这个数组使用mapp[i]=mapp[i]+mapp[i-1]的方式把它记录的值变为数组到这个位置的和,这样的好处就是任意一个区间[i,j]的和就可转化为了mapp[i]-mapp[j-1]。在这里我们依然采用这样的技巧。我们把这个矩阵记录的值对于每个列向量都做上述改变。
然后我们就发现,但我们选取任意的连续行进行组合的时候,这个行区间对于的列的值的和都可以用上述方法快速获得,那么对于每个列的和又会变为一个求一维连续区间最大和问题了。到此这个问题就可以以O(n^2)的复杂度解决了。
代码:
#include <math.h> #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> const int maxn=102; int mapp[maxn][maxn]; #define mem(a,b) memset(a,b,sizeof(a)) int main() { int i,j,k,tt,T,r,c,max,temp; scanf("%d",&T); while(T--) { mem(mapp,0); scanf("%d%d",&r,&c); for(i=1; i<=r; i++) { for(j=0; j<c; j++) { scanf("%d",&mapp[i][j]); mapp[i][j]+=mapp[i-1][j]; } } for(i=1,tt=mapp[1][0]; i<=r; i++) for(j=i; j<=r; j++) { for(k=max=0; k<c; k++) { temp=mapp[j][k]-mapp[i-1][k]; max=(max>=0?max:0)+temp; tt=max>tt?max:tt; } } printf("%d\n",tt); } return 0; }