L1-7 To the Max

给出一个由正整数和负整数组成的二维数组,一个子矩形是指位于整 个数组中大小为1*1或更大的任何连续子数组。矩形的和是该矩形中所 有元素的和。在本题中,具有最大和的子矩形被称为最大子矩形。 例如,给出一个二维数组如下:

\begin{matrix} 0 & -2 & -7 & 0\\ 9 & 2 & -6 & 2\\ -4 & 1 & -4 & 1\\ -1 & 8 & 0 & -2 \end{matrix}

最大子矩形是在左下角:

\begin{matrix} 9 & 2\\ -4 & 1\\ -1 & 8 \end{matrix}

矩形的和是15。

输入格式:

输入给出一个N*N个整数组成的数组。输入的第一行给出一个正整数N,表示二维正方形数组的大小。后面给出用空白字符(空格和换行符)分隔的N2个整数。这些整数是数组的N2 个整数,以行为顺序按行给出。也就是说,首先,第一行从左到右,给出第一行的所有数字;然后,再第二行从左到右,给出第二行的所有数字,以此类推,N的最大值可以是100。数组中的数字的范围是[-127, 127]。

输出格式:

输出最大子矩形的和。

输入样例:

在这里给出一组输入。例如:

4
0 -2 -7 0 
9 2 -6 2 
-4 1 -4 1 
-1 8 0 -2

输出样例:

在这里给出相应的输出。例如:

15

 思路:

看题意不难想到使用动态规划来解,本题思路与LeetCode-304. 二维区域和检索 - 矩阵不可变题解大同小异,可以看一下力扣对此题的官方图解

简单来说就是维护一个数组dp,dp[i][j]表示在matrix[i][j]左上方的矩形区域内所有元素的和。

Q: 但是子矩形不一定是从matrix[0][0]开始啊?

A: 只需要遍历每一个位置,定为子矩形的左上角,再遍历左上角的所有右下区域的每一个坐标,根据sum = dp[i-1][j-1] - dp[p][j-1] - dp[i-1][q] + dp[p][q]; 就能算出每一个子矩形(左上角为[i, j],右下角为[p, q])的和了

参考代码:

#include<bits/stdc++.h>
using namespace std;

const int MAXSIZE = 100+10;
int dp[MAXSIZE][MAXSIZE];
int matrix[MAXSIZE][MAXSIZE];

int main() {
    int n;  cin>>n;
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=n;++j) {
            cin>>matrix[i][j];
            dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + matrix[i][j];
        }
    }
    int res = -128;
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=n;++j) {
            for(int p=i;p<=n;++p) {
                for(int q=j;q<=n;++q) {
                    res = max(res, dp[i-1][j-1] - dp[p][j-1] - dp[i-1][q] + dp[p][q]);
                }
            }
            
        }
    }
    cout<<res<<endl;
    return 0;
}

上面的代码由于从matrix[1][1]开始记录数据,所以不需要考虑边界情况,但意思可能不够直观的,也可以从matrix[0][0]开始记录数值:

#include<bits/stdc++.h>
using namespace std;

const int MAXSIZE = 100+10;
int dp[MAXSIZE][MAXSIZE];
int matrix[MAXSIZE][MAXSIZE];

int main() {
    int n;  cin>>n;
    for(int i=0;i<n;++i) {
        for(int j=0;j<n;++j) {
            cin>>matrix[i][j];
        }
    }
    dp[0][0] = matrix[0][0];
    for(int i=1;i<n;++i) {
        dp[0][i] = dp[0][i-1] + matrix[0][i];
        dp[i][0] = dp[i-1][0] + matrix[i][0];
    }
    for(int i=1;i<n;++i) {
        for(int j=1;j<n;++j) {
            dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + matrix[i][j];
        }
    }
    int res = -128;
    int curSum = 0;
    for(int i=0;i<n;++i) {
        for(int j=0;j<n;++j) {
            for(int p=i;p<n;++p) {
                for(int q=j;q<n;++q) {
                    curSum = 0;
                    if(j > 0) curSum += -dp[p][j-1];
                    if(i > 0) curSum += -dp[i-1][q];
                    if(i > 0 && j > 0) curSum += dp[i-1][j-1];
                    res = max(res, curSum + dp[p][q]);
                }
            }
            
        }
    }
    cout<<res<<endl;
    return 0;
}

 

posted @   Coder-Jiang  阅读(4)  评论(0编辑  收藏  举报  
努力加载评论中...
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起