티스토리 뷰

https://www.acmicpc.net/problem/11660

 

11660번: 구간 합 구하기 5

첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네

www.acmicpc.net

x1, y1 부터 x2, y2 까지의 합을 구하는 문제입니다.
얼핏보면 n이 최대 1024라 그냥 다 더하면 될 거 같지만 100000번 수행해야 하므로 브루트포스로는 안 됩니다. 

dp를 이용해 1,1부터 x,y까지의 합을 먼저 구하면 다음과 같습니다.
dp[i][j] = num + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]
(num : 해당 위치 숫자)

그리고 x1, y1 ~ x2, y2까지의 합은 결국 사각형을 그려보면 1,1 ~ x2, y2까지 합에서 1,1 ~ x2, y1-1까지 합 + 1,1 ~ x1-1, y2 까지 합 - 1,1 ~ x1-1, y1-1 까지 합 임을 알 수 있습니다.

코드는 다음과 같습니다.

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// dp[i][j] = num + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]
// x1, y1 ~ x2, y2까지 합
// dp[x2][y2] - (dp[x2][y1-1] + dp[x1-1][y2] - dp[x1-1][y1-1])

int n, m;
int map[1025][1025];
int dp[1025][1025]; // [1][1] ~ [x][y] 까지 합

void init()
{
	cin >> n >> m;
	
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> map[i][j];
		}
	}
}

void getDP()
{
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			dp[i][j] = map[i][j];
			dp[i][j] += dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];
		}
	}
}

int getResult(int x1, int y1, int x2, int y2)
{
	return dp[x2][y2] - (dp[x2][y1 - 1] + dp[x1 - 1][y2] - dp[x1 - 1][y1 - 1]);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	init();
	getDP();
	while (m--) {
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		cout << getResult(x1, y1, x2, y2) << '\n';
	}
}

 

'알고리즘 > 백준' 카테고리의 다른 글

백준 16953 A -> B C++  (0) 2022.07.01
백준 11000 강의실 배정 C++  (0) 2022.06.02
백준 2210 숫자판 점프 C++  (0) 2022.05.06
백준 12904 A와 B C++  (0) 2022.04.07
백준 15486 퇴사 2 C++  (0) 2022.04.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함