https://www.acmicpc.net/problem/11660
N * N 크기의 표에서 (x1, y1)부터 (x2, y2)까지 합을 구하라
입력
첫 번째 줄 : N M
N : 표의 w, h
M : 찾을 횟수
N개 줄
표 정보 표기
M개 줄 : x1 y1 x2 y2
출력
M줄 만큼 구간 합 구하기
이 문제는 첫 번째 한 행 또는 한 열씩 누적합을 구한 후, 반복을 통해서 구할 수 있습니다.
(각 줄에 대한 누적합이 별도로 존재)
이 방법은 구간 합 구하기 4문제와 매우 유사한 풀이법을 가지게 됩니다.
조금 더 심화적인 방법으로는 2차원 배열의 누적합을 구한 후 누적합 배열을 사용하여 문제를 풀 수 있습니다.
해당 방법은
1) 누적합 구하기
2) 결과 값 계산하기
와 같은 순서로 진행됩니다.
1) 누적합 구하기
문제의 입력 예시를 통해서 설명드리도록 하겠습니다.
A[][] 배열을 이용하여 누적합을 구할 S[][] 배열을 완성시켜야 합니다.
S[][] 배열의 각 위치의 값은
S[i][j] = S[i][j - 1] + S[i - 1][j] + A[i][j] - S[i - 1][j - 1]
와 같은 식으로 구할 수 있습니다.
가령 S[2][2] 위치의 값을 구하기 위해서는,
S[2][1](노란색)과 S[1][2]의 값(파란색), 그리고 현재 위치인 A[2][2]를 더하면 됩니다.
이 때 S[1][1](초록색)은 노란색 부분의 누적합과, 파란색 부분의 누적합에 모두 포함되게 됩니다.
(S[1][1]은 S[2][1]과 S[1][2]를 더하면 두 번 포함 됨)
따라서 한 번 값을 빼줘야 하기 때문에 S[1][1]을 빼게 됩니다.
동일한 방법을 전체 배열을 돌면서 수행하면 누적합 배열 S[][]가 완성됩니다.
2) 결과 값 계산하기
x1, y1, x2, y2를 이용하여 우리가 원하는 구간의 구간합을 구하는 것이 최종 목표입니다.
S[x2][y2]를 기준으로 포함되지 않는 부분을 빼는 연산을 수행한다면 구할 수 있습니다.
마찬가지로 2 2 3 4 예시를 통해 살펴보면
S[3][4]를 기준으로 하여 포함되지 않는 S[1][4](노란색)와 S[3][1](초록색)를 뺀다면 결과를 구할 수 있을 것입니다.
이때 S[][]를 구할 때와 동일하게 파란 부분이 중복되어 들어가는 현상이 발생합니다.
(S[1][1]이 두 번 빠짐)
따라서 최종적으로 파란 부분인 S[1][1]을 한 번 더해주면 됩니다.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[][] a = new int[N + 1][N + 1];
int[][] s = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= N; j++) {
a[i][j] = Integer.parseInt(st.nextToken());
}
}
// 누적 합 구하기
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
s[i][j] = s[i][j - 1] + s[i - 1][j] + a[i][j] - s[i - 1][j - 1];
}
}
// print(s);
// 구간 합 구하기
for (int tc = 0; tc < M; tc++) {
st = new StringTokenizer(br.readLine());
int sr = Integer.parseInt(st.nextToken());
int sc = Integer.parseInt(st.nextToken());
int er = Integer.parseInt(st.nextToken());
int ec = Integer.parseInt(st.nextToken());
int answer = s[er][ec] - s[sr - 1][ec] - s[er][sc - 1] + s[sr - 1][sc - 1];
System.out.println(answer);
}
}
public static void print(int arr[][]) {
System.out.println();
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[0].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
해당 코드는 에디터가 코드 연습을 위해 직접 작성하였습니다.
혹시 오류가 있거나 더 좋은 코드 방향성을 아시는 분은 댓글로 남겨주시면 감사하겠습니다!
python source : https://github.com/ssh5212/conding-test-practice
java source : https://github.com/ssh5212/coding-test-java
[Baekjoon] 백준 1261 알고스팟 (G5^ / 다익스트라) - Python (0) | 2024.03.22 |
---|---|
[Baekjoon] 백준 1753 최단경로 (G4^ / 다익스트라) - Python (0) | 2024.03.20 |
[인프런] 최대 길이 연속 부분 수열 (투 포인터^) (2) | 2024.01.10 |
[코딩테스트] Java 첫 코딩 테스트 시작 시 문법 정리 (2) | 2023.12.20 |
[Baekjoon] 백준 5582 공통 부분 문자열 (G5^ / DP) - Java (0) | 2023.10.31 |