当前位置:首页 > 题解目录 > 正文内容

【题解】最大子矩阵

亿万年的星光2年前 (2023-06-05)题解目录1482

【题目描述】

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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]。

【输出描述】

输出最大子矩阵的大小。

【样例输入】

4
0 -2 -7  0
9  2 -6  2
-4  1 -4  1
-1  8  0 -2

【样例输出】

15

【题目分析】

  • 二维数组其实可以看做一维数组

  • 需要用到  最大字段和 的知识


我们处理二维数组,按照行的数据进行处理,按列求出最大值。

for(i=1;i<=n;i++)
		for(j=1;j<=n;j++){
			scanf("%d",&jz[i][j]);
			jz[i][j]+=jz[i][j-1];
		}

那么,jz数组求出来以后的结果是:

0 -2 -9 -9
9 11 5 7
-4 -3 -7 -6
-1 7 7 5

可以看出,上面的结论是按照行数据,每一个数都是这一行的前面几个数的求和。


【参考代码】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int jz[105][105]={0};
int main()
{
	int n,i,j;
	scanf("%d",&n);
	//求二维数组的前缀和
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++){
			scanf("%d",&jz[i][j]);
			jz[i][j]+=jz[i][j-1];
		} 
	int sum,max=-1000000000;
	//最大字段和的思想
	for(i=1;i<=n;i++)
		for(j=i;j<=n;j++){
			sum=0;
			for(int k=1;k<=n;k++){
				sum+=jz[k][j]-jz[k][i-1];
				if(sum>max)
					max=sum;
				if(sum<0)
					sum=0;
			}	
		}
	printf("%d\n",max);
	return 0;
}

上面的代码中 ,jz数组求的是二维数组的前缀和。后面求最大字段和除了借鉴前面的思想还可以借助下面的过程:

  1. 初始状态是二维数组(i表示行,j表示列)


    j=1j=2j=3j=4
    i=1
    1,11,21,31,4
    i=22,12,22,32,4
    i=33,13,23,33,4
    i=44,14,24,34,4

当i=1时,我们可以访问(1,1),(1,2),(1,3)(1,4)

当i=2时,我们可以访问(2,2),(2,3),(2,4)

当i=3时,我们可以访问(3,3),(3,4)

当i=4时,我们可以访问(4,4)

也就是下面这样


j=1j=2j=3j=4
i=1
1,11,21,31,4
i=22,12,22,32,4
i=33,13,23,33,4
i=44,14,24,34,4

但是,实际上,上面的代码是三重循环,也就是上图中,所有绿色的点都要执行最内部的一遍for循环。

比如,当(i,j)=(1,1)时,这时最内层循环看jz[k][j]和jz[k][i-1]的变化关系是

k j  -  k  i-1
1 1     1  0   
2 1     2  0  
3 1     3  0
4 1     4  0

这相当于二维数组中第一列每一个数都判断了一遍最大值。

......

当(i,j)=(1,2)时,,这时内层循环看jz[k][i]和 jz[k][i-1]的变化关系是

k j  -  k  i-1
1 2     1  0   
2 2     2  0  
3 2     3  0
4 2     4  0

因为jz数组存的是和的关系。这个地方表示是前两列,每个数相比的最大值。

......

当(i,j)=(2,2)时,,这时内层循环看jz[k][i]和 jz[k][i-1]的变化关系是

k j  -  k  i-1
1 2     1  1   
2 2     2  1  
3 2     3  1
4 2     4  1

这个时候实际上是第二列,因为减法减去了第一列的值

......



扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

标签: dp动态规划
分享给朋友:

相关文章

【题解】最短距离

【题目描述】在一条一维的直线上,存在着 n 台显示器和 n 个电源插座。老师给小蓝布置了个任务:负责将每台显示器通过电源线与一个插座相连接(每个插座最多只能给一...

【题解】单词排序

【题目描述】输入一行单词序列,相邻单词之间由一个或者多个空格间隔,请按照字典序输出这些单词,要求重复的单词只输出一次。(区分大小写)【输入描述】一行单词序列,最少一个单词,最多100个单词,每个单词长...

连词成句

【题目描述】有一天,毛毛上课的时候遇到了一个难题,老师让同学们把黑板上的单词连成一句话。已知连词的规则是:从待选词中选出正确的单词按照顺序输出,“正确的单词”表示除第一个单词外,其余单词都是小写字母,...

【题解】滑翔翼

【题目描述】小T和小K都是OIER,入选省队后有幸去苏州参加JSOI集训,训练之余,他们相约一起去苏州乐园玩。苏州乐园里有一个非常热门的游乐项目叫双人滑翔翼。小T想和小K一起乘双人滑翔翼,但是排在他们...

【题解】移动路线

【题目描述】X桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。小明是个调皮的孩子,一...

【题解】报数游戏

【题目描述】路飞在和他朋友们一块玩一个游戏。由于路飞的机智,这个游戏由路飞担任裁判。首先,路飞会给他们一个人一个编号,并且每个人的编号都不相同。接下来的每一个回合,会给一个数,编号不超过它的最大编号的...