最大子矩阵 贪心

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]; 

都值得学习。

这样看来由这个题可以发散的出很多种求最小类似字母型的矩阵(这样还叫矩阵吗)的和,没事想想处理方法也挺有意思的。

 

 

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页