首先考虑一维的情况。我们可以把问题转化为:
for(i=0;i<MAX;i++)以a[i]结束的最大子数组和。
而以a[i]结束的最大子数组和必须包含他自己,那么他包不包含前面的数呢?
这就看前面对构成一个比他大的子数组和有没有贡献,即前面的数组和是不是大于0.
这样我们从a[0]开始,每次得到的结果就都会被下一次用到。这样只需要O(N)就可以找出最大的子数组和。
而清楚了一维之后,二维只需要枚举上下边界即可。
1 #include<stdio.h>
2 #include<string.h>
3 int FindMax(int a[],int n)
4 {
5 int b[100],wtf=-1<<30;
6 int i;
7 for(i=0;i<n;i++)
8 b[i]=a[i];
9 for(i=1;i<n;i++)
10 {
11 if(b[i-1]>0)
12 b[i]+=b[i-1];
13 if(wtf<b[i])
14 wtf=b[i];
15 }
16 return wtf;
17 }
18 int main()
19 {
20 int n;
21 scanf("%d",&n);
22 int a[100][100];
23 memset(a,0,sizeof(a));
24 int i,j;
25 for(i=0;i<n;i++)
26 for(j=0;j<n;j++)
27 scanf("%d",&a[i][j]);
28 int up,down;
29 int temp[100],record,final=-1<<30;
30 for(up=0;up<n;up++)
31 {
32 memset(temp,0,sizeof(temp));
33 for(down=up;down<n;down++)
34 {
35 for(j=0;j<n;j++)
36 temp[j]+=a[down][j];
37 record=FindMax(temp,n);
38 if(record>final)
39 final=record;
40 }
41 }
42 printf("%d\n",final);
43 return 0;
44 }
这个题是POJ的1050题。。我就不测试了。
![]()