[ 백준 ] 16507 / 어두운 건 무서워

金弘均·2021년 9월 16일
0

Baekjoon Online Judge

목록 보기
169/228
post-thumbnail

# Appreciation

/*
 * Problem :: 16507 / 어두운 건 무서워
 *
 * Kind :: Math
 *
 * Insight
 * - (r1,c1)=(1,1) 그리고 (r2,c2)=(N,N) 이며
 *   max(Q)=10000 번 주어진다고 했을 때,
 *   각 쿼리마다 매번 포함된 칸을 하나씩 센다면 시간초과가 날 수밖에 없다
 *   + 밝기의 합을 저장해놓고 사용할 수는 없을까? <= Dynamic Programming
 *     누적합을 이용하자!
 *     # dp[i][j] = (1,1)~(i,j) 칸의 합
 *       -> (r1,c1)~(r2,c2) 칸의 합은 위를 이용해서
 *          dp[r2][c2] - dp[r1-1][c2] - dp[r2][c1-1] + dp[r1][c1] 으로 구할 수 있다!
 * Point
 * - (r1,c1)=(1,1) 인 경우
 *   dp[r1-1][c2] = dp[0][c2]
 *   dp[r2][c1-1] = dp[r2][0]
 *   dp[r1][c1] = dp[0][0] 이 된다
 *   + 문제에서는 좌표가 0 이 될 수 없지만 위와같은 예외를 처리하기 위해
 *     코드에서는 y좌표나 x좌표가 0 이 될 수 있으며 각 칸의 값은 0 으로 간주하자
 *     # 따라서, (i,j) 에서 i 나 j 가 0 이면 dp[i][j] = 0 이다
 *       -> dp[i][j] = (0,0)~(i,j) 칸의 합
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <cstring>

using namespace std;

#define endl '\n'

// Set up : Global Variables
/* None */

// Set up : Functions Declaration
/* None */


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int R, C, Q;
    cin >> R >> C >> Q;
    int P[R+1][C+1];
    memset(P, 0, sizeof(P));
    for (int i=1; i<=R; i++) {
        for (int j=1; j<=C; j++) {
            cin >> P[i][j];
        }
    }

    // Process
    int dp[R+1][C+1]; /* dp[i][j] = (0,0)~(i,j) 칸의 합 */
    memset(dp, 0, sizeof(dp)); /* (0,0)~(0,C) 와 (0,0)~(R,0) 칸의 밝기는 0 */
    for (int i=1; i<=R; i++) {
        for (int j=1; j<=C; j++) {
            /* (0,0)~(i,j) 칸의 합
             *      =
             * (i,j) 칸의 값
             *      +
             * (0,0)~(i,j-1) 칸의 합
             *      +
             * (0,0)~(i-1,j) 칸의 합
             *      -
             * (0.0)~(i-1,j-1) 칸의 합 */
            dp[i][j] = P[i][j] + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1];
        }
    }

    // Control : Output
    for (int i=0; i<Q; i++) {
        int r1, c1, r2, c2;
        cin >> r1 >> c1 >> r2 >> c2;

        int size = (r2-r1+1)*(c2-c1+1); /* 칸의 개수 */
        /* (r1,c1)~(r2,c2) 칸의 합
         *        =
         * (0,0)~(r2,c2) 칸의 합
         *        -
         * (0,0)~(r2,c1-1) 칸의 합
         *        -
         * (0,0)~(r1-1,c2) 칸의 합
         *        +
         * (0,0)~(r1-1,c1-1) 칸의 합 */
        int sum = dp[r2][c2] - dp[r1-1][c2] - dp[r2][c1-1] + dp[r1-1][c1-1];
        cout << sum / size << endl;
    }
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이

0개의 댓글