Baekjoon

[백준 DP] 11660번 - 구간 합 구하기 5

yujin0517 2022. 12. 28. 14:29

11660번 - 구간 합 구하기 5

 

<문제>

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

 

11660번: 구간 합 구하기 5

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

www.acmicpc.net

 

<문제 풀이>

문제 접근은 쉽다. 값을 입력 받아 배열에 저장하고 시작점부터 끝점까지의 누적 합을 구하면 된다. 

시간초과될 것을 알면서도 일단은 이중 for문을 사용하여 코드를 작성하고 제출해봤다. 

 좌표값을 입력 받을 때 사용하는 이중 for문은 필요한 과정이라고 생각을 했고, 누적 합을 구하는 과정에서 사용되는 이중 for문을 없애보려 코드 수정을 해보았다. 

이 과정에서 2차원 배열을 하나 더 생성하였고 새로 생성한 2차원 배열에는 (1, 1) -> (a, b)까지의 누적 합을 저장했다. 

Ex)

arr[][]     -->   dp[][]

1   2             1     3

3   4             4     10

문제에서 좌표 값을 입력 받을 때 위와 같이 누적 합도 같이 저장했다. 

하지만 dp 배열에 저장되어 있는 값은 시작점이 무조건 (1, 1)이다. 문제는 시작점이 (1, 1)이 아닐 수도 있다는 점이다.

만약 (1, 2) -> (2, 2)를 입력 받았다고 해보자. 

문제에서 원하는 출력 값은 6이다. dp[2][2]에는 출력 값을 구하는 데 필요없는 arr[1][1], arr[2][1]의 값이 누적 되어있다. 

결과적으로 문제에서 원하는 답은 dp[2][2]에서 dp[2][1]의 값을 뺀 값이다. 

2x2 배열에서는 점화식이 잘 보이지 않지만 문제 예시에 있는 4x4 배열에서는 점화식을 찾을 수 있을 것이다. 

점화식(입력): dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j]
점화식(출력): dp[x2][y2] - (dp[x1 - 1][y2] + dp[x2][y1 - 1] - dp[x1 - 1][y1 - 1])

 

<코드>

  • 시간초과 코드
더보기
#include <iostream>
using namespace std;

int N, M;
int dp[1025][1025] = { 0, };

int main() {
	cin >> N >> M;

	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> dp[i][j];
		}
	}

	int sum;
	int x1, x2, y1, y2;
	while (M-- > 0) {
		sum = 0;
		cin >> x1 >> y1 >> x2 >> y2;

		for (int i = x1; i <= x2; i++) {
			for (int j = y1; j <= y2; j++) {
				sum += dp[i][j];
			}
		}
		
		cout << sum << endl;
	}

	return 0;
}

 

  • 해결 코드
더보기
#include <iostream>
using namespace std;

int N, M;
int arr[1025][1025] = { 0, };
int dp[1025][1025] = { 0, };

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

	cin >> N >> M;

	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> arr[i][j];
			dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j];
		}
	}

	int sum;
	int x1, x2, y1, y2;
	while (M-- > 0) {
		sum = 0;
		cin >> x1 >> y1 >> x2 >> y2;
		
		sum = dp[x2][y2] - (dp[x1 - 1][y2] + dp[x2][y1 - 1] - dp[x1 - 1][y1 - 1]);
		cout << sum << '\n';
	}

	return 0;
}

 

<결과>

 

 

2022.12.28

'Baekjoon' 카테고리의 다른 글

[백준 DP] 2293번 - 동전 1  (0) 2023.01.04
[백준 DP] 11048번 - 이동하기  (0) 2022.12.28
[백준 DP] 11057번 - 오르막 수  (0) 2022.12.22
[백준 DP] 12865번 - 평범한 배낭  (0) 2022.12.19
[백준 DP] 1010번 - 다리 놓기  (0) 2022.12.18