Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 31864 | Accepted: 16615 |
Description
As an example, the maximal sub-rectangle of the array:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
is in the lower left corner:
9 2
-4 1
-1 8
and has a sum of 15.
Input
Output
Sample Input
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
Sample Output
15
Source
(1)s(i1,i2,j1,j2)=a[i1][i2]+a[i1][i2+1]+……+a[i][j]+……+a[j1][j2];(i1<=i<=i2;j1<=j<=j2)
推导后可以得到类似一维的最大字段和的问题。下面为算法:
max_sum_submatrix(int m,int n,int a[][n])
{
int sum=-99999999;
int max;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
b[j]=0;
}
for(j=i;j<=n;j++)
{
for(k=1;k<=n;k++)
{
b[k]+=a[j][k];
}
max=max_sum_subseq(n,b);
sum=sum>max?sum:max;
}
}
下面举例说明:
如矩阵:
当i=1时,初始化数组b,使得
b:0 0 0
当j=1时,k从1递增到n,由算法的第15行可得数组b将首先存储矩阵的第一行的各值,即b为:
b:-2
由最大子序列和的函数max_sum_subseq()返回该序列的最大子序列的和值为max=30;
当j=2时,k从1递增到n,由算法的第15行可得数组b将矩阵a第二行的值分别加到原有各值上,可得数组b为
同理,返回该序列的最大子序列的和值为max=125。
当j=3时,k从1递增到n,由算法的第15行可得数组b将矩阵a第三行的值分别加到原有各值上,可得数组b为
b:98
同理,返回该序列的最大子序列的和值为max=120。
到此,i的第一次循环结束。
当i=2时,从新初始化数组b,使得
b:0
j=2时,k从1递增到n,由算法的第15行可得数组b将首先存储矩阵的第二行的各值,即b为:
b:100
返回该序列的最大子序列的和值为max=100。
j=3时,k从1递增到n,由算法的第15行可得数组b将矩阵a第三行的值分别加到原有各值上,可得数组b为
b:100
返回该序列的最大子序列的和值为max=92。
到此,i的第二次循环结束。
当i=3循环结束时,可求出该矩阵的最大子矩阵和值为125。
下面是poj1050的代码:
#include <cstdio>
using namespace std;
int n;
int array[110][110];
int temp[110];
int max_sum_subseq()
{
int i,res,tmp[110];
for(i=1;i<=n;i++)
{
tmp[i]=temp[i];
}
res=tmp[1];
for(i=2;i<=n;i++)
{
tmp[i]=tmp[i]>tmp[i]+tmp[i-1]?tmp[i]:tmp[i]+tmp[i-1];
res=res>tmp[i]?res:tmp[i];
}
return res;
}
int main()
{
int i,j,k;
int sum=-99999999,max;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&array[i][j]);
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
temp[j]=0;
}
for(j=i;j<=n;j++)
{
for(k=1;k<=n;k++)
{
temp[k]+=array[j][k];
}
max=max_sum_subseq();
sum=sum>max?sum:max;
}
}
printf("%d\n",sum);
return 0;
}