二维数组前缀和(差分)以及枚举所有矩形(子矩阵)

就变成了上面的红色部分。
那么假设红色部分左上角坐标为(x1,y1)(x1,y1),右下角为(x2,y2)(x2,y2),设sum[x][y]sum[x][y]表示从(1,1)(1,1)加到(x,y)(x,y)的和,那么红色部分就是:
sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]sum[x2][y2]−sum[x2][y1−1]−sum[x1−1][y2]+sum[x1−1][y1−1]
那么sum[x][y]sum[x][y]要怎么求呢?
其实就是xx这一行到yy的前缀和加上sum[x-1][y]sum[x−1][y]就Ok啦~~
可以自己理解一下(应该很好理解吧)
然后呢,再用4个变量循环判断坐标,然后求最大值即可。
代码如下:
#include<iostream>
using namespace std;
int n;
int a[130][130];//存储题目中的矩阵
int sum[130][130];
int qz[130][130];//qz[i][j]指的是第i行到j的前缀和
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
qz[i][j]=qz[i][j-1]+a[i][j];//求前缀和
sum[i][j]=qz[i][j]+sum[i-1][j];//计算sum
}
}
int mx=-99999999;//存储答案
for(int x1=1;x1<=n;x1++){
for(int y1=1;y1<=n;y1++){
for(int x2=1;x2<=n;x2++){
for(int y2=1;y2<=n;y2++){
if(x2<x1 || y2<y1) continue;//如果左上角比右下角还要大,就不用求了,下一个
mx=max(mx,sum[x2][y2]+sum[x1-1][y1-1]-sum[x2][y1-1]-sum[x1-1][y2]);//求最大值
}
}
}
}
cout<<mx;//输出
return 0;
}

由二维差分数组d得到更新的a矩阵代码如下
#include <stdio.h> #include <string.h> #define maxn 10 int a[maxn][maxn],sum[maxn][maxn],d[maxn][maxn]; int main(){ int i,j; for(i=1;i<=6;i++) for(j=1;j<=6;j++) a[i][j]=1;//a[i][j]矩阵建立 memset(d,0,sizeof(d)); d[3][3]+=1,d[3][4+1]-=1,d[4+1][3]-=1,d[4+1][4+1]+=1;//a[i][j]子矩阵(3,3)-(4,4)区间每个元素+1 二维差分数组建立 for(i=1;i<=7;i++) for(j=1;j<=7;j++) d[i][j]+=d[i][j-1]+d[i-1][j]-d[i-1][j-1];//二维差分数组建立 for(i=1;i<=6;i++) for(j=1;j<=6;j++) a[i][j]+=d[i][j];//a[i][j]矩阵的更新 for(i=1;i<=6;i++){ for(j=1;j<=6;j++) printf("%d\t",a[i][j]); printf("\n"); } return 0; }

浙公网安备 33010602011771号