• 最大子矩阵和


    最大子矩阵和 $ n^3 $ 算法



    $ solution: $

    首先我们不难想到枚举上下左右边界,然后两层循环统计权值和,复杂度 $ O(n^6) $ 。这个我们用前缀和可以省去后面的循环,将复杂度降成 $ O(n^4) $ 。然后我们考虑不枚举上下左右四个边界,我们只枚举其中的上边界和下边界,于是题目转化成一个一维找权值最大区间。

    于是我们考虑一个问题:怎样求一个数列的最大子段和。这个用DP可以做,设 $ f[i] $ 表示以 $ i $ 为右端点的最大字段和, $ f[i]=max(f[i-1]+a[i],a[i]) $ 这个我们可以 $ O(n) $ 计算。

    于是我们求出这整个矩阵的向上的前缀和 $ s[i][j]=a[i][j]+s[i-1][j] $ ,这个可以 $ O(1) $ 求出上述一维状态下的权值。

    总复杂度 $ O(n^3) $



    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define rg register int
    
    using namespace std;
    
    int n,ans;
    int s[105][105];
    int a[105],f[105];
    
    inline int qr(){
    	register char ch; register bool sign=0; rg res=0;
    	while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    	while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    	if(sign)return -res; else return res;
    }
    
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	n=qr(); f[0]=-1e9; ans=-1e9;
    	for(rg i=1;i<=n;++i)
    		for(rg j=1;j<=n;++j)
    			s[i][j]=s[i-1][j]+qr();
    	for(rg i=0;i<n;++i)
    		for(rg j=i+1;j<=n;++j)
    			for(rg k=1;k<=n;++k){
    				a[k]=s[j][k]-s[i][k];
    				f[k]=max(f[k-1]+a[k],a[k]);
    				ans=max(ans,f[k]);
    			}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Bufferedreader和BufferedWriter(带缓存的输入输出)
    FileReader和FileWriter
    Map接口的类实现
    Map接口
    Set集合
    List接口的实现类
    获取文本框或密码框中的内容
    ADTS (zz)
    初级美语 L003:My Family 解析
    初级美语 L001:Self Introduction 解析
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/11252431.html
Copyright © 2020-2023  润新知