https://www.acmicpc.net/problem/11660
11660번: 구간 합 구하기 5
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네
www.acmicpc.net
문제 해결 과정
착안
이차원 배열 내에서 $x_1$행 $y_1$열을 좌상단, $x_2$행 $y_2$열을 우하단($x_2 \geq x_1, \space y_2 \geq y_1$)으로 하는 사각형 내의 숫자들의 누적 합을 계산하기 위해, 주어진 이차원 배열과 크기가 같은 배열을 선언하여 동적계획법(dynamic programming)에 활용한다. 이때, 메모이제이션을 위한 행렬 $DP$의 $i$행 $j$열의 요소($=DP[i][j]$)에 1행 1열을 좌상단, $i$행 $j$열을 우하단으로 하는 사각형 내의 숫자들의 총합으로 저장한다.
위와 같이 미리 계산된 값을 사용하면, $x_1$행 $y_1$열을 좌상단, $x_2$행 $y_2$열을 우하단으로 하는 사각형 모양 내에 있는 숫자들의 누적 합 $S(x_1, y_1, x_2, y_2)$는 다음과 같이 계산할 수 있다.
$$S(x_1, y_1, x_2, y_2) = S(1, 1, x_2, y_2) - S(1, 1, x_1 - 1, y_2) - S(1, 1, x_2, y_1 - 1) + S(1, 1, x_1 - 1, y_1 - 1)$$
$$= DP[x_2][y_2] - DP[x_1 - 1][y_2] - DP[x_2][y_1 - 1] + DP[x_1 - 1][y_1 - 1]$$
구현
배열 $DP[i][j]$에 1행 1열을 좌상단, $i$행 $j$열을 우하단으로 하는 사각형 내의 숫자들을 누적한 값을 저장하는 부분에 유의하여 프로그래밍 하였다.
[스포 주의] 아래 '더보기'를 누르면 코드가 나오니 주의하세요~
#include <iostream>
using namespace std;
int DP[1025][1025];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int N, M;
cin >> N >> M;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
{
cin >> DP[i][j];
DP[i][j] += DP[i - 1][j] + DP[i][j - 1] - DP[i - 1][j - 1];
}
while (M--)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << DP[x2][y2] - DP[x1 - 1][y2] - DP[x2][y1 - 1] + DP[x1 - 1][y1 - 1] << "\n";
}
return 0;
}
실행 결과
'C++ 코딩 문제 풀이 > 백준' 카테고리의 다른 글
[Baekjoon] 1068번: 트리 (0) | 2023.12.01 |
---|---|
[Baekjoon] 1012번: 유기농 배추 (0) | 2023.08.24 |
[Baekjoon] 14502번: 연구소 (0) | 2023.08.15 |
[Baekjoon] 17179번: 케이크 자르기 (0) | 2023.08.14 |
[Baekjoon] 16493번: 최대 페이지 수 (0) | 2023.08.08 |
댓글