题目描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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]。
输出描述:
测试数据可能有多组,对于每组测试数据,输出最大子矩阵的大小。
示例1
输入
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
输出
15
时间复杂度
O(n4)
思路
本题输入规模最大100,用动态规划可以做到O(n3)。下面暴力思路是O(n4),但是思路简单,代码简单。
枚举矩阵中每两两个坐标,用前缀和优化求子矩阵的过程。只要给出两个左上角,和右上角的坐标,就能求子矩阵。
求和:s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
求子矩阵(a,b,c,d): = s[c][d] - s[a-1][d] - s[c][b-1] + s[a-1][b-1];
代码
#include <iostream>
using namespace std;
const int N = 101;
int sum[N][N];
int n;
void get(int x,int y,int &max)//左上角是(x,y),右下角是(i,j)
{
for(int i = x; i <= n; i ++)
{
for(int j = y +1 ; j <=n ; j++)
{
int t = sum[i][j] - sum[x-1][j] - sum[i][y-1] + sum[x-1][y-1];
//cout<< t <<endl;
if(t > max){
max = t;
}
}
}
}
int main()
{
while(cin>>n)
{
for(int i = 1; i <=n ; i++)
{
for(int j = 1; j <= n ; j++)
{
int t; cin>>t;
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + t;
}
}
int max = 0x80000001;
for(int i = 1; i <= n ; i++)
{
for(int j = 1; j <= n ; j ++)
{
get(i,j,max);
}
}
cout<<max<<endl;
}
}


京公网安备 11010502036488号