day23 126 maximum sum (two-dimensional prefix sum)

126. The Largest Sum

Given a two-dimensional matrix containing integers, a sub-rectangle is any 1 * 1continuous sub-array with a size of or greater within the entire array.

The sum of the rectangle is the sum of all the elements in the rectangle.

In this problem, the sub-rectangle with the largest sum is called the largest sub-rectangle.

For example, the following array:

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

The largest sub-rectangle is:

9 2
-4 1
-1 8

It has a maximum sum of 15.

Input format The
input will contain a N ∗ NN*NNAn integer array of N.

Enter only an integer NN in the first lineN represents the size of the square two-dimensional array.

Starting from the second line, enter N 2 N^2 separated by spaces and newlinesN2 integers, they areN 2 N^2 inthe two-dimensional arrayN2 elements, the input sequence starts from the first row of the two-dimensional array and enters downwards row by row, and the same row of data is entered one by one from left to right.

The numbers in the array will remain in the range of [-127,127].

Output format
Output an integer, which represents the sum of the largest sub-rectangle.

Data range
1 ≤ N ≤ 100 1 ≤ N ≤ 1001N. 1 0 0
Input Sample:

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

Sample output:

15

Ideas

Suppose we s[i][j]represent from (0,0)location to (i,j)all elements of the position and is s[i][j]calculated as shown below:
Insert picture description here
then to (x1, y1)the upper left corner, (x2, y2): sub-matrix lower right corner of demand and how it as shown below?
Insert picture description here
Prefixed with a two-dimensional array And, we only need to enumerate all the sub-matrices and find the maximum value.

Java code

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[][] arr = new int[n + 1][n + 1];//避免下标转换
        int[][] s = new int[n + 1][n + 1];//前缀和数组
        //读取数据
        for(int i = 1;i <= n ;i++){
    
    
            for(int j = 1;j <= n;j++){
    
    
                arr[i][j] = scanner.nextInt();
            }
        }

        //计算二维前缀和s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + arr[i][j]
        //这里就显示了我们将下标设置为成1开始的优势了,i - 1最小也是0,而s[0][j]默认都是0,公式中加上0也没事
        //但如果下标从0开始,则s[i-1][j]中的i-1可能会下标越界,需要我们特判,增加麻烦
        for(int i = 1;i <= n;i++){
    
    
            for(int j = 1;j <= n;j++){
    
    
                s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + arr[i][j];
            }
        }

        int res = Integer.MIN_VALUE;
        for(int x2 = 1;x2 <= n;x2++){
    
    
            for(int y2 = 1;y2 <= n;y2++){
    
    //枚举子矩阵的右下角(x2,y2)
                for(int x1 = 1;x1 <= x2;x1++){
    
    
                    for(int y1 = 1;y1 <= y2;y1++){
    
    //枚举子矩阵的左上角(x1,y1) 注for中条件为: (x1,y1)<= (x2,y2)
                        res = Math.max(res,s[x2][y2] - s[x1 -1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
                    }
                }
            }
        }
        System.out.println(res);
    }
}

Insert picture description here

Guess you like

Origin blog.csdn.net/YouMing_Li/article/details/113917601