题目描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 × 1)子矩阵。
比如,如下4 × 4的矩阵:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
最大子矩阵是:
9 2
-4 1
-1 8
这个子矩阵的大小是15。
输入格式
输入是一个N×N的矩阵。输入的第一行给出N。
输出格式
输出最大子矩阵的大小。
输入输出样例
输入
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
输出
15
分析:
这道题需要我们在数组中找到一个矩形,使矩形中的数总和最大,就像是最大字段和的二维版本,这里我们依然可以用之前最大字段和的方法。(详见最大字段和(C++解法))
首先先写输入:
#include<bits/stdc++.h>
using namespace std;
int n,a[105][105],f[105][105],sum,imax=-100000;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
这里用之前最大字段和的方法,不同的是这次的计算与之前不同:
方法一:
1.[1,1]处等于原值;
2.[1,n]处等于原值加[1,n-1]处的值(n不等于1);
3.[n,1]处等于原值加[n-1,1]处的值(n不等于1);
4.剩余处等于[m-1,n]处加[m,n-1]处;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==1&&j==1) f[1][1]=a[1][1];
else if(i==1) f[i][j]=f[i][j-1]+a[i][j];
else if(j==1) f[i][j]=f[i-1][j]+a[i][j];
else f[i][j]=f[i-1][j]+a[i][j-1]+a[i][j];
}
}
方法二:
用一个公式可以轻松解决:
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=a[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
}
接着就是输出矩阵和,这里我们需要将矩阵中的和算出来,这里可以用一个公式计算:
for(int h=1;h<=n;h++)
{
for(int hc=0;hc<=n-h;hc++)
{
for(int l=1;l<=n;l++)
{
for(int lc=0;lc<=n-l;lc++)
{
imax=max(imax,f[h+hc][l+lc]-f[h+hc][l-1]-f[h-1][l+lc]+f[h-1][l-1]);
}
}
}
}
最后输出就完成了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[105][105],f[105][105],sum,imax=-100000;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=a[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
}
for(int h=1;h<=n;h++)
{
for(int hc=0;hc<=n-h;hc++)
{
for(int l=1;l<=n;l++)
{
for(int lc=0;lc<=n-l;lc++)
{
imax=max(imax,f[h+hc][l+lc]-f[h+hc][l-1]-f[h-1][l+lc]+f[h-1][l-1]);
}
}
}
}
cout<<imax;
return 0;
}