고인물을 지양하는 블로그

BOJ 2167 2차원 배열의 합 본문

Algorithms/ACMICPC(백준)

BOJ 2167 2차원 배열의 합

yunjaeGong 2019. 7. 23. 21:54

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

 

2167번: 2차원 배열의 합

첫째 줄에 배열의 크기 N, M(1 ≤ N, M ≤ 300)이 주어진다. 다음 N개의 줄에는 M개의 정수로 배열이 주어진다. 배열에 포함되어 있는 수는 절댓값이 10,000보다 작거나 같은 정수이다. 그 다음 줄에는 합을 구할 부분의 개수 K(1 ≤ K ≤ 10,000)가 주어진다. 다음 K개의 줄에는 네 개의 정수로 i, j, x, y가 주어진다(i ≤ x, j ≤ y).

www.acmicpc.net

주말에 놀다 글 쓰는걸 잊어버려.. 저번 주에 

 

문제 풀기 교수님께서 말씀하셨던 dp 문제였다.

재귀식과 구현은 어렵지 않았지만, 중복 처리가 미흡해 한~참 헤맸다.

 

#include <cstdio>
int dp[301][301];
int main() {
    int N,M,K,i,j,x,y;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d",&dp[i][j]);
    // 누적합 계산
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            dp[i][j] += (dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]);
        // dp[i-1][j-1]이 중복됨.

    scanf("%d",&K);
    while(K) {
        scanf("%d%d%d%d",&i,&j,&x,&y);
        printf("%d\n",dp[x][y]-dp[x][j-1]-dp[i-1][y]+dp[i-1][j-1]);
        // 중복돼 빠진 dp[i-1][j-1]를 더해줌
        K--;
    }
}

dp[i][j]를 다음과 같이 정의하자

dp[i][j]: (i, j)까지의 누적 합 (단, i,는 y좌표)

 

(i,j)까지의 누적 합은 다음과 같이 구해진다.

(i-1,j), (i,j-1)까지 누적합의 합 - (i-1,j-1) (중복해서 더해진 (i-1,j-1)까지의 누적합)

따라서 누적합은 다음과 같이 구해진다.

코드에서 input은 dp[i][j]

x,y까지의 누적 합에서 i,j 바로 왼쪽 열, 윗행을 빼면 (i,j)에서 (x,y)까지의 누적 합 -(i-1,j-1)까지의 누적합이 된다.

(i,j 바로 왼쪽 열, 윗행을 빼는 과정에서 (i-1,j-1)까지 누적합이 두번 빠짐)

 

따라서 재귀식은 다음과 같다.

'Algorithms > ACMICPC(백준)' 카테고리의 다른 글

BOJ 14499 주사위  (0) 2019.08.02
BOJ 5568 카드 놓기  (0) 2019.07.26
BOJ 1912 연속합  (0) 2019.07.17
BOJ 4948 베르트랑 공준  (0) 2019.07.16
BOJ 11726 2 x n 타일링  (0) 2019.07.15
Comments