最大子矩阵和 题解
已知矩阵的大小定义为N*N的矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空子矩阵。
输入的第一行给出N(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127]。
输出最大子矩阵的大小。
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
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。
今天为大家讲解一道经典dp题--------最大子矩阵和,小编建议先去温习一下《最大子段和》这道题(因这题是最大子矩阵和的基础)。读题后乍一看没有思路,其根本原因其实是因为矩阵的变化太多端无法确立一个固定的状态转移方程。故有一个思路为,用循环将矩阵压缩成一串字段存储,将问题简化成求其最大子段和的解。最后打个擂台,将最大子段和计入ans,最终ans即为最大子矩阵和,即为正解。
#include<iostream>
#include<cstring>
using namespace std;
int h(int f[],int n)
{
int a=f[1],ans=a,i;
for(i=2;i<=n;i++)
{
a=max(a,0)+f[i];
ans=max(ans,a);
}
return ans;
}//求出其最大子段和的自定义函数(具体解析请看小编对于最大子段和的题解)
int main()
{
int n,a[101][101],i,j,f[101],k;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>a[i][j];
}
}//二层循环输入矩阵
int ans=-1270010;//ans,一定要设的足够小。
for(i=1;i<=n;i++)
{
memset(f,0,sizeof(f));//将存储压缩矩阵的数组初始化为0
for(j=i;j<=n;j++)
{
for(k=1;k<=n;k++)
{
f[k]+=a[j][k];//一层层的压缩矩阵,并计入f[i]数组(也可以用二分的哈)
}
ans=max(ans,h(f,n));//“打擂台”,将用自定义函数求出的最大子段和计入ans
}
}
cout<<ans<<endl;//输出正解ans
return 0;//完美结束
}