문제
N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다.
예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.
1 | 2 | 3 | 4 |
2 | 3 | 4 | 5 |
3 | 4 | 5 | 6 |
4 | 5 | 6 | 7 |
여기서 (2, 2)부터 (3, 4)까지 합을 구하면 3+4+5+4+5+6 = 27이고, (4, 4)부터 (4, 4)까지 합을 구하면 7이다.
표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오.
입력
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네 개의 정수 x1, y1, x2, y2 가 주어지며, (x1, y1)부터 (x2, y2)의 합을 구해 출력해야 한다. 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수이다. (x1 ≤ x2, y1 ≤ y2)
출력
총 M줄에 걸쳐 (x1, y1)부터 (x2, y2)까지 합을 구해 출력한다.
내가 푼 풀이
- 연산의 최대횟수가 100,000이고, 배열의 크기가 최대 1024이므로 단순히 주어진 연산의 범위만큼 반복문을 돌리면,
최악의 경우 연산횟수가 100,000 * 1024 * 1024나 되므로, 계산된값을 저장하고 이용하기로 했다.
- 주어진 (N+1) x (N+1) 크기의 배열 dp를 선언한다.
- 행과 열이 인덱스가 0인경우 0을 넣어준다.
- dp[i][j] = 1행 1열부터 i행 j열까지 더한 범위의 값이라고 정의하자.
- (x1, y1) , (x2, y2) 가 주어졌을때,
- 예시로 4 x 4 배열이 주어졌을때, (2, 2) (3,4)의 범위는 아래와같다.
0 | 0 | 0 | 0 | 0 |
0 | ||||
0 | ||||
0 | ||||
0 |
이 범위의 연산결과는 아래처럼 나타낼 수 있다.
0 | 0 | 0 | 0 | 0 |
0 | ||||
0 | ||||
0 | ||||
0 |
위의 큰 배열에서
0 | 0 | 0 | 0 | 0 |
0 | ||||
0 | ||||
0 | ||||
0 |
0 | 0 | 0 | 0 | 0 |
0 | ||||
0 | ||||
0 | ||||
0 |
위 두가지 범위를 빼준 후
0 | 0 | 0 | 0 | 0 |
0 | ||||
0 | ||||
0 | ||||
0 |
이 범위를 더해주면 된다.
이를 0,0부터 i,j까지의 연산범위합이 들어간 dp[i][j]를 이용하면 아래와 같이 나타낼 수 있다.
- dp[3][4] - dp[1][4] - dp[4][1] + dp[1][1]
위 공식을 이용해서 연산결과들을 출력한다.
(x1, y1) , (x2, y2) 의 범위가 주어졌을때, 해당 범위의 연산결과는
dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1]
import Foundation
var counts = readLine()!.split(separator: " ").map{ Int($0)! }
var arr = [Array(repeating: 0, count: counts[0] + 1)]
var dp = Array(repeating: Array(repeating: 0, count: counts[0] + 1), count: counts[0] + 1)
// 주어진 n x n 배열 저장
// (n+1) x (n+1) 크기로 저장하고, 행렬의 인덱스가 0이면 0 저장
for i in 0..<counts[0] {
arr.append([0] + readLine()!.split(separator: " ").map{ Int($0)! })
}
// dp[i][j] = 0,0 부터 i,j까지 모두 합한 결과를 저장
for i in 1..<dp.count {
for j in 1..<dp.count {
dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + arr[i][j]
}
}
// 해당 범위만큼의 연산결과 출력
for i in 0..<counts[1] {
var inputs = readLine()!.split(separator: " ").map{ Int($0)! }
let x1 = inputs[0]
let y1 = inputs[1]
let x2 = inputs[2]
let y2 = inputs[3]
print(dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1])
}
'코딩테스트 > 백준' 카테고리의 다른 글
BOJ-2187 미로 탐색 Swift (1) | 2023.05.25 |
---|---|
BOJ-14916 거스름돈 Swift (0) | 2023.05.24 |
BOJ-1260 DFS와 BFS Swift (0) | 2023.05.20 |
BOJ-2847 게임을 만든 동준이 Swift (0) | 2023.05.20 |
BOJ-11054 가장 긴 바이토닉 부분수열 Swift (0) | 2023.05.20 |