最大和
- 描述
-
给定一个由整数组成二维矩阵(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。
思路: 1,预处理每一列的和 sum[i][j] : 第j列从0到第i行的和
e.g.:sum[3][2]=a[1][2]+a[2][2]+a[3][2];
2 三重循环: 第一重枚举高度从1 到n;
第二重枚举一点 (i,j)去计算矩阵 (i-h,,j) 到 (i,j)间的和; 此时就可以当作一维的数组找最大和;
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
int pos[110][110];
int dp[110][110][110];
int sum[110][110];
int main()
{
// freopen("in.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&pos[i][j]);
for(int j=0;j<=m;j++) pos[0][j]=0;
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
{
sum[i][j]=sum[i-1][j]+pos[i][j];
// printf("sum[%d][%d]=%d\n",i,j,sum[i][j]);
}
memset(dp,0,sizeof(dp));
int ans=pos[1][1];
for(int h=1;h<=n;h++)
{
for(int i=h;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(dp[h][i][j-1]<=0)
dp[h][i][j]=sum[i][j]-sum[i-h][j];
else dp[h][i][j]=dp[h][i][j-1]+sum[i][j]-sum[i-h][j];
//printf("dp[%d][%d][%d]: %d\n",h,i,j,dp[h][i][j]);
ans=max(ans,dp[h][i][j]);
}
}
}
printf("%d\n",ans);
}
return 0;
}