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 ^ 2엔2 개 요소의 경우 입력 시퀀스는 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);
}
}