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

就变成了上面的红色部分。

那么假设红色部分左上角坐标为(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][y11]sum[x11][y2]+sum[x11][y11]

那么sum[x][y]sum[x][y]要怎么求呢?

其实就是xx这一行到yy的前缀和加上sum[x-1][y]sum[x1][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;
}

 

posted @ 2021-02-28 22:46  旅玖旅玖  阅读(67)  评论(0编辑  收藏  举报