티스토리 뷰
https://www.acmicpc.net/problem/15724
15724번: 주지수
네모 왕국의 왕인 진경대왕은 왕국의 영토를 편하게 통치하기 위해서 1X1의 단위 구역을 여러 개 묶어서 하나의 거대 행정구역인 주지수(州地數, 마을의 땅을 셈)를 만들 예정이다. 진경대왕은
www.acmicpc.net
✨ 문제 풀이
(1,1)부터 (i, j)까지의 인구수 합을 저장하는 dp 배열을 memo[i][j]라고 하자
위에 그림과 같이
빨간 네모 + 초록색 네모 - 빨간 네모와 초록색 네모가 겹치는 네모 + 그 부분의 인구수
를 계산하면 (i, j)까지의 인구수 누적합이다
이를 점화식으로 세우면
(i, j)의 인구수 + (1,1)부터 (i-1, j)까지의 인구수 합 + (1, 1)부터 (i, j-1)까지의 인구수 합 - (1,1)부터 (i-1, j-1)까지의 인구수 합
이다.
그리고 우리가 원하는 건 (1,1)부터가 아닌 (x, y)부터 이다.
위에서 누적합을 구하기 위해 더하고 중복값을 빼주었던 것처럼 이번엔 반대로 빼주고 중복으로 빠진 값을 더해주면 된다
위 그림에서 보라색 네모의 인구수를 구한다고 해보자. 그럼
(4,4)까지의 인구수 합 - (초록색 네모 + 빨간 네모 - 빨간 네모와 초록색 네모가 겹치는 네모)
가 된다.
이를 점화식으로 세우면
(1, 1)부터 (i, j)까지의 인구수합 - ((1, 1)부터 (x-1, j)까지의 인구수 합 + (1, 1)부터 (i, y-1)까지의 인구수 합 - (1, 1)부터 (x-1, y-1)까지의 인구수 합)
이다.
코드로 작성하면 다음과 같다
#include <iostream>
using namespace std;
int N, M, K;
int total[1025][1025];
int memo[1025][1025];
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= M; j++)
{
cin >> total[i][j];
memo[i][j] = total[i][j] + memo[i - 1][j] + memo[i][j - 1] - memo[i - 1][j - 1];
}
}
for (int index = 1; index <= K; index++)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << memo[x2][y2] - (memo[x1 - 1][y2] + memo[x2][y1 - 1] - memo[x1 - 1][y1 - 1]) << '\n';
}
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준/c++] 17129 윌리암슨수액빨이딱따구리가 정보섬에 올라온 이유 (0) | 2022.04.07 |
---|---|
[c++] n*m 격자 무늬, 행렬 BFS 알고리즘 문제 코드 (0) | 2022.04.07 |
Graph 알고리즘 (0) | 2022.04.07 |
[프로그래머스/python] 입국심사 (0) | 2022.03.26 |
[백준/c++] 12865 평범한 배낭 (0) | 2022.03.17 |