📜  2D矩阵中的最大和矩形| DP-27(1)

📅  最后修改于: 2023-12-03 14:38:51.304000             🧑  作者: Mango

2D矩阵中的最大和矩形 | DP-27

简介

在二维矩阵中,找出元素总和最大的子矩阵。

这是一个动态规划问题,我们需要遍历所有可能的子矩阵,并计算它们的总和。最终返回总和最大的子矩阵即可。

解题思路
  1. 以每一行为底部,计算该行向上的矩形的最大子数组和;
  2. 对于该行及以上所有可能的矩形,计算它们的总和;
  3. 返回总和最大的矩形。
代码示例
#include<bits/stdc++.h>
#define ll long long
#define RI register int
using namespace std;
const int N=1e3+6;
int a[N][N];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    ll ans=INT_MIN;
    for(int i=1;i<=n;i++){ // 以每一行为底部
        int x[N],top=0;
        memset(x,0,sizeof(x));
        for(int j=i;j<=n;j++){ // 计算该行及以上所有可能的矩形
            int sum=0;
            for(int k=1;k<=m;k++){ // 计算子数组和
                x[k]+=(a[j][k]==0?-1:1); // 将0转为-1,转化为最大子段和问题
                sum+=x[k];
            }
            ans=max(ans,1ll*sum);
            int amin=x[1],amax=x[1],sum_now=x[1]; //进一步使用Kadan算法优化
            for(int k=2;k<=m;k++){
                sum_now=max(x[k],sum_now+x[k]);
                amax=max(amax,sum_now);
                amin=min(amin,sum_now);
            }
            if(amax<=0){//特判
                ans=max(ans,1ll*amax);
                continue;
            }
            if(amin<0){
                sum=0;
            }else{
                sum=amax;
            }
            for(int k=1;k<=m;k++){
                sum=amax;
                for(int z=k;z<=m;z++){
                    sum+=x[z];
                    ans=max(ans,1ll*sum);
                    if(sum<=0)break;
                }
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

这里使用了Kadane算法优化求子数组和的过程。

Kadane算法是一个用于求解最大连续子数组和的算法,它的时间复杂度为O(n)。

参考资料

Kadane算法