(POJ) 1050 To the Max

传送门

题目大意:给你一个矩阵,求里面的最大子矩阵(求和最大)。

解题思路:第一想法当然是暴力枚举了,当然立即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;
}

猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/84940531
今日推荐