题目描述
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
其中,A的子矩阵指在A中行和列均连续的一块。
样例说明
取最后一列,和为10。
数据规模和约定
对于100%的数据,1< =n, m< =500,A中每个元素的绝对值不超过5000。
输入
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
输出
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出
10
思路
在选定子矩阵中我们要先选定行范围载选定列范围
for example:对于如下矩阵
-1 -4 3
3 4 -1
-5 -2 8
1先看0-0行矩阵,设为subMx,再在该子矩阵subMx中选取对应连续的列来确定在0-0行子矩阵(设为subsubMx)中最大的子矩阵,此时最大的subsubMx=3;
2又来到0-1行矩阵subMx,不像1中只有一列很好比较,我们需要一个一维数组sub[]用于存储subMx中对应列的和。在1中数组sub的值应该是-1,-4,3;在此例中sub的值应该是-1+3,-4+4,3-1即-2,0,2,此时最大的subsubMx=2;
3重复类似2的操作走到0-2行
*4走到1-1行
*5走到1-2行
*6走到2-2行
结束
#include<iostream>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;
int n,m;
int mp[505][505];
int getmax(int sub[])
{
int maxx,tmp,begin;
maxx=-inf;
begin=sub[0];
for(int i=1;i<m;i++)
{
if(begin+sub[i]>sub[i])
begin=begin+sub[i];
else
begin=sub[i];
if(begin>maxx)
maxx=begin;
}
return maxx;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&mp[i][j]);
int tmp;
int ans=-inf;
for(int i=0;i<n;i++)//枚举行级子矩阵第i行到第j行
{
int sub[505]={0};//sub用于求第i行到第j行的对应第k列元素之和
for(int j=i;j<n;j++)
{
int k;
for(k=0;k<m;k++)
sub[k]+=mp[j][k];
tmp=getmax(sub);//得到行级子矩阵的列级子矩阵的最大值 也就是求第i行到第j行这个子矩阵里0-m列中最大的子矩阵
if(tmp>ans)
ans=tmp;
}
}
cout << ans;
}