题目大意:给你一个矩阵,求里面的最大子矩阵(求和最大)。
解题思路:第一想法当然是暴力枚举了,当然立即pass,复杂度过高,那再用前缀和处理一下的,这样复杂还是过高的。直接枚举是肯定不现实的。那我们直接枚举上界呢,然后将它下面的一层一层的加上去,每加一次都算一次最大子序列和。比如枚举第i层作为上界,求出此时的最大子序列和就是以i为上界,宽为1的最大子矩阵;在将i+1层的数依此加上第i层,再求一次,此时求出的就是以i为上界,宽为2的最大子矩阵。
那样例举个栗子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2 枚举第一层为上界
tmp数组 最长子序列和
1. 0 -2 -7 0 0
2. 9 0 -13 2 (第二层加上第一层) 9
3. 5 1 -17 3 (继续累加) 6
4. -4 9 -17 -1(继续累加) 9 所以以第一层为上界的最大子矩阵和为9
例:第三步选出的矩阵就是 0 -2
9 2
-4 1
这样枚举的复杂度就是O(n^3) (枚举上界n,枚举宽n,求最长子序列和n)
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1e3+5;
int m[maxn][maxn],ttres;
int tmp[maxn],n,ans=-1;
int main(){
cin>>n;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
cin>>m[i][j];
}
}
for(int i=1;i<=n;++i){
memset(tmp,0,sizeof(tmp));
for(int j=i;j<=n;++j){
ttres=0;
for(int k=1;k<=n;++k){
tmp[k]+=m[j][k];
ttres+=tmp[k];
ans=max(ans,ttres);
if(ttres<0) ttres=0;
}
}
}
cout<<ans<<endl;
return 0;
}