day23126 최대 합계 (2 차원 접두사 합계)

126. 가장 큰 합계

정수를 포함하는 2 차원 행렬이 주어지면 하위 직사각형은 전체 1 * 1배열 내에서 크기가 크 거나 같은 연속 하위 배열입니다.

사각형의 합은 사각형에있는 모든 요소의 합입니다.

이 문제에서는 합이 가장 큰 부분 직사각형을 가장 큰 부분 직사각형이라고합니다.

예를 들어, 다음 배열 :

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

가장 큰 하위 직사각형은 다음과 같습니다.

9 2
-4 1
-1 8

최대 합계는 15입니다.

입력 형식
입력에는 N ∗ NN * N 이 포함됩니다.N 의 정수 배열입니다 .

첫 번째 줄에는 정수 NN 만 입력하십시오.N 은 정사각형 2 차원 배열의 크기를 나타냅니다.

두 번째 줄부터 공백과 줄 바꿈으로 구분하여 N 2 N ^ 2를 입력합니다.2 개의 정수,2차원 배열에서 N 2 N ^ 22 개 요소의 경우 입력 시퀀스는 2 차원 배열의 첫 번째 행에서 시작하여 행별로 입력되고 동일한 데이터 행이 왼쪽에서 오른쪽으로 하나씩 입력됩니다.

배열의 숫자는 [-127,127] 범위로 유지됩니다.

출력 형식
가장 큰 하위 직사각형의 합을 나타내는 정수를 출력합니다.

데이터 범위
1 ≤ N ≤ 100 1 ≤ N ≤ 1001. 1 0 0
입력 샘플 :

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

샘플 출력 :

15

아이디어

우리 s[i][j](0,0)위치 에서 위치의 (i,j)모든 요소 나타내며 s[i][j]아래와 같이 계산 된다고 가정 합니다 :
여기에 사진 설명 삽입
그런 다음 (x1, y1)왼쪽 상단 모서리로, (x2, y2): 수요의 하위 매트릭스 오른쪽 하단 모서리와 아래 그림과 같이 어떻게됩니까?
여기에 사진 설명 삽입
2 차원 배열로 접두사 및, 모든 부분 행렬을 열거하고 최대 값을 찾기 만하면됩니다.

자바 코드

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);
    }
}

여기에 사진 설명 삽입

추천

출처blog.csdn.net/YouMing_Li/article/details/113917601