Description
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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。
Input
输入是一个N×N的矩阵。输入的第一行给出N(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127]。
Output
输出最大子矩阵的大小。
Sample Input
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
Sample Output
15
Source
#include<iostream>
using namespace std;
int a[101][101];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
cin >> a[i][j];
a[i][j] += a[i][j-1];//a[i][j]表示第i行 ,1到j列的数值之和
}
// int num, x, y;
// for(int i = 1; i <= n*n; i++)//另一种存法
// {
// cin >> num;
// x = (i-1)/n + 1;
// y = i%n;
// if(y == 0)
// y = n;
// a[x][y] = num;
// a[x][y] += a[x][y-1];
// }
int max = -1, m = 0;
for(int i = 0; i < n; i++)
for(int k = i+1; k <= n; ++k)
{
m = 0;
for(int j = 1; j <= n; j++)
{
m += a[j][k] - a[j][i];
if(m > max)
max = m;
if(m < 0)
m = 0;
// if(m >= 0) // 另一种写法
// m += a[j][k] - a[j][i];
// else
// m = a[j][k] - a[j][i];
// if(m > max)
// max = m;
}
}
cout << max;
}
这个题的跟求最大子序列类似,这算题动规吧?,最大的子矩阵和要么在前面,要么在后面,要么在中间,取两个变量m,max,m为不断累加的值,累加到小于等于0时就置零,保证后面加到的数不受前面影响。在累加过程中由max存最大的m值。
对矩阵的数据处理:
a[i][j] += a[i][j-1];// a[i][j]保存第i行1~j列数值之和
或者 a[i][j] += a[i-1][j]//a[i][j]保存第j列1~i行数值之和
通过三层循环依次计算每个矩阵的和 m += a[k][j] - a[k][i] 或者 m+= a[j][k] - a[i][k];
都值得学习。
这样看来由这个题可以发散的出很多种求最小类似字母型的矩阵(这样还叫矩阵吗)的和,没事想想处理方法也挺有意思的。