본문 바로가기

알고리즘/python

[python/파이썬] 백준 11660 구간 합 구하기 5

반응형

문제

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)까지 합을 구해 출력한다.

예제 입력 1 복사

4 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
2 2 3 4
3 4 3 4
1 1 4 4

예제 출력 1 복사

27
6
64

예제 입력 2 복사

2 4
1 2
3 4
1 1 1 1
1 2 1 2
2 1 2 1
2 2 2 2

예제 출력 2 복사

1
2
3
4

 

[소스 코드1 - 시간 초과]

 

시간 초과 나올 거 알았지만 혹시나 해서 해본 코드이다.

역시나 시간 초과가 나오기에 시도도 안 하는 게 좋을 것 같다.

n, m = map(int, input().split())

arr = []

for i in range(n):
    a = list(map(int, input().split()))
    arr.append(a)
    
def sum_arr(x1, y1, x2, y2):
    sum = 0
    for row in range(x1-1, x2):
        for col in range(y1-1, y2):
            sum += arr[row][col]
    return sum
            
for i in range(m):
    x1, y1, x2, y2 = map(int, input().split())
    result = sum_arr(x1, y1, x2, y2)
    print(result)

 

[문제 풀이]

 

누적합을 이용해야 하는 문제이다.

누적합을 구하고 그 값을 다시 연산해서 내가 원하는 값을 구해야 하는 문제이다.

 

1 2 3
2 3 4
3 4 5

이러한 2차원 배열이 존재할 때 누적합을 나타내는 배열은 아래와 같다

1 1 + 2 1 + 2 + 3
1 + 2 1 + 2 + 2 +3 1 + 2 + 2 + 3 + 3 + 4
1 + 2 + 3 1 + 2 + 2 + 3 + 3 + 4 1 + 2 + 2+ 3 + 3 + 3 + 4 + 4 + 5 

 

 

여기에서 (x1, y1), (x2, y2)가 주어졌을 때 우리는 x1행부터 x2행까지, y1열부터 y2열까지의 요소들의 합을 구해야 한다.

 

만일 (2, 2), (3, 3)이라고 할 때 아래와 같이 숫자가 쓰인 부분의 합만 구해야 한다.

 

     
  3 4
  4 5

 

그러기 위해서는 누적합을 저장한 배열인 dp를 아래와 같은 방식으로 연산해야 한다.

 [소스 코드2 - 맞았습니다!]

import sys
input = sys.stdin.readline

n, m = map(int, input().split())

arr = []
for i in range(n):
    a = list(map(int, input().split()))
    arr.append(a)
    
dp = [[0]*(n+1) for i in range(n+1)]

for i in range(1, n+1):
    for j in range(1, n+1):
        dp[i][j] = dp[i][j-1] + dp[i-1][j] - dp[i-1][j-1] + arr[i-1][j-1]
        
for k in range(m):
    x1,y1,x2,y2 = map(int,input().split())
    
    result = dp[x2][y2] - dp[x2][y1-1] -dp[x1-1][y2] + dp[x1-1][y1-1]
    print(result)
반응형