📅  最后修改于: 2023-12-03 14:38:51.304000             🧑  作者: Mango
在二维矩阵中,找出元素总和最大的子矩阵。
这是一个动态规划问题,我们需要遍历所有可能的子矩阵,并计算它们的总和。最终返回总和最大的子矩阵即可。
#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)。