描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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 (0 < N <= 100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[-127, 127]。
输出
输出最大子矩阵的大小。
=======================================================================================================================================================================================================================
刚拿到这道题的时候 一点思路也没有
所以....
我搜题解去了
(好吧...这样不好)
发现一种更有意思的东西
矩阵前缀和
在这里先简单点儿
--------------------------------------------
就在下面
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(a:元素,sum:从a(1,1)到a(i,j)所有值的和,就是前缀和。)
边读入边求前缀和(sum),用这个公式来求:①+②+③-④ 得出sum(5,3)=a(5,3)+sum(4,2)+sum(5,2)-sum(4,2);
好像有点递推思想呢?
然后四重循环暴力枚举所有子矩阵,找到最大值!
公式:①-②-③+④,枚举出(2,2)到(5,3)的矩阵大小t=sum(5,3)-sum(5,1)-sum(1,3)+sum(1,1),更新最大值。
这时候 就稍稍有点思路了
以下是代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int n,b[110][110],a[110][110],maxn,q,w,e,r;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
scanf("%d",&a[i][j]);
b[i][j]= a[i][j] + b[i-1][j] + b[i][j-1] - b[i-1][j-1]; //算出1.1到i.j矩阵所有元素的和
}
for(q = 1;q <= n;++q)
for(w = 1;w <= n;++w)
for(e = 1;e <= q;++e)
for(r = 1;r <= w;++r)
{
maxn=max(maxn,b[q][w] + b[e-1][r-1] - b[q][r-1] - b[e-1][w]); //反向想 算出e.r到q.w之间矩阵的元素和 并和先已知的最大值比较 若比它大 就替换
printf("%d",maxn);
return 0;
}
无后效性:
每个位置上的元素是确定的 得到的矩阵的最大值不会影响元素的值