문제
https://www.acmicpc.net/problem/2167
2167번: 2차원 배열의 합
첫째 줄에 배열의 크기 N, M(1 ≤ N, M ≤ 300)이 주어진다. 다음 N개의 줄에는 M개의 정수로 배열이 주어진다. 배열에 포함되어 있는 수는 절댓값이 10,000보다 작거나 같은 정수이다. 그 다음 줄에는
www.acmicpc.net
문제 요약
N × N 크기의 2차원 배열을 입력 받고, 위치 (i, j) 부터 (x, y) 까지 있는 수들의 합을 출력한다.
+ (i, j), (x, y)는 배열의 i(x)번째 행, j(y)번째 열을 의미한다. (1부터 시작)
코드
import sys
input = sys.stdin.readline
N, M = map(int, input().rstrip().split())
arr = [list(map(int, input().rstrip().split())) for _ in range(N)]
# N개의 행과 M개의 열을 갖는 배열
K = int(input())
# 합을 구할 부분의 개수
psum = [[0] * (M + 1) for _ in range(N + 1)]
for i in range(1, N + 1):
for j in range(1, M + 1):
psum[i][j] = psum[i-1][j] + psum[i][j-1] - psum[i-1][j-1] + arr[i-1][j-1]
# <이전 행 누적합> + <이전 열 누적합> - <이전 행, 열 누적합> + <현재 인덱스 값>
# <이전 행, 열 누적합>을 빼주는 이유는 <이전 행 누적합>과 <이전 열 누적합>을 더할 때 <이전 행, 열 누적합>이 두 번 더해지기 때문
print(*psum)
for _ in range(K):
i, j, x, y = map(int, input().rstrip().split())
print(psum[x][y] - psum[x][j-1] - psum[i-1][y] + psum[i-1][j-1])
# 그림 참고
코드 설명
1. N개의 행과 M개의 열을 갖는 배열 arr에 대한 누적합 배열 psum을 생성한다.
+ psum은 N+1개의 행과 M+1개의 열을 갖는 배열이다. (초기 행과 열을 0으로 설정)
예) 배열 arr
1 | 4 | 4 | 9 |
3 | 2 | 7 | 6 |
5 | 2 | 8 | 8 |
예) 배열 psum의 초기 상태
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
1-1. psum[i][j] (arr[i-1][j-1] 까지의 누적합)을 psum[i-1][j] (이전 행 누적합) + psum[i][j-1] (이전 열 누적합) - psum[i-1][j-1] (이전 행, 열 누적합) + arr[i-1][j-1] (현재 인덱스의 arr값)으로 설정한다.
+ psum[i-1][j-1]을 빼주는 이유는 psum[i-1][j], psum[i][j-1]을 더할 때, psum[i-1][j-1]이 두 번 더해지기 때문이다.
예) 배열 psum[i][j] 값을 할당한 상태
0 | 0 | 0 | 0 | 0 |
0 | 1 | 5 | 9 | 18 |
0 | 4 | 10 | 21 | 30 |
0 | 9 | 17 | 36 | 59 |
2. (i, j) 부터 (x, y) 범위에 있는 수들의 합을 구한다.
예) (2, 2) 부터 (3, 4) 범위 수 구하기
0 | 0 | 0 | 0 | 0 |
0 | 1 | 5 | 9 | 18 |
0 | 4 | 10(i, j) | 21 | 30 |
0 | 9 | 17 | 36 | 59(x, y) |
psum(x, y)에서
0 | 0 | 0 | 0 | 0 |
0 | 1 | 5 | 9 | 18 |
0 | 4 | 10 | 21 | 30 |
0 | 9 | 17 | 36 | 59 |
psum[x][j-1]을 빼주고
0 | 0 | 0 | 0 | 0 |
0 | 1 | 5 | 9 | 18 |
psum[i-1][y]를 빼주고
0 | 0 |
0 | 1 |
0 | 4 |
0 | 9 |
두 번 뺀 psum[i-1][j-1]을 다시 더해준다.
0 | 0 |
0 | 1 |
'Algorithm Problems > 누적 합' 카테고리의 다른 글
[백준/C++] 25682번: 체스판 다시 칠하기 2 (0) | 2024.07.29 |
---|---|
[백준/C++] 25606번: 장마 (0) | 2024.07.25 |
[백준/C++] 28420번: 카더가든 (0) | 2024.05.20 |
[백준/C++] 10986번: 나머지 합 (0) | 2024.04.05 |
[백준/C++] 2042번: 구간 합 구하기 (0) | 2024.04.04 |