【题目描述】
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1×11×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(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127]。
【输出】
输出最大子矩阵的大小。
【输入样例】
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
【输出样例】
15
题目分析
1.前缀和的理解,对于一个点(i,j)前缀和为:f[i][j] = a[i][j] + f[i][j - 1] + f[i - 1][j] - f[i - 1][j - 1];
每一个框是一个子矩阵,用S1记录每个子矩阵右下角元素的前缀和
黑色框是大矩阵,红色框是要求和的矩阵,记作S0
橙色框记作S1
蓝色框记作S2
绿色框记作S3
粉色框记作S4
所以S0=S1-S2-S3+S4
AC代码
#include <bits/stdc++.h>
using namespace std;
int a[105][105],n,s=-10000000;
int f[105][105];
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++)
{
for(int h=1;h<=i;h++)
{
for(int l=1;l<=j;l++)
{
f[i][j]+=a[h][l];
}
}
}
}
for (int i=1;i<=n;i++)//枚举左上角行坐标
{
for (int j=1;j<=n;j++)//枚举左上角列坐标
{
for (int h=i;h<=n;h++)//枚举右下角行坐标
{
for (int l=j;l<=n;l++)//枚举右下角列坐标
{
//开始求出子矩阵的大小和,并比较
s=max(s,f[h][l]-f[i-1][l]-f[h][j-1]+f[i-1][j-1]);
}
}
}
}
cout<<s;
return 0;
}