[ 백준 ] 1520 / 내리막 길

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
48/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 1520 / 내리막 길
 *
 * Kind :: Dynamic Programming + Graph
 *
 * Insight
 * - BFS 로 풀면 되겠다
 *   + 시간초과네
 *     # 경로를 일일이 세니까 문제다
 *       그러고보니 최대 경로의 수가 10억이네 ㄷㄷ
 *       -> BFS 로는 못 풀겠다
 *
 * - 아무래도 DP 를 활용해서 경로의 수를 저장해야 할듯 싶다
 *   + dp[i][j] = (1,1) -> (i,j) 이동 가능한 경로의 수
 *     # dp[i][j] 는 상하좌우 인접한 칸들(ai,aj) 중
 *       현재 칸보다 높이가 더 높은 칸들의 dp[ai][aj] 의 합으로 구할 수 있다!
 *       -> 현재 칸보다 높이가 더 높은 인접한 칸들이 없다면 dp[i][j] = 0 이다
 *          => 제일 왼쪽 위 칸에서 시작해야되니 dp[0][0] = 1 로 초기화 해야한다
 *
 * Point
 * - 편의상 제일 왼쪽 위 칸을 (1,1) 이 아니라 (0,0) 으로 설정하였다
 */

# Code

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

#include <iostream>
#include <cstring>

using namespace std;

#define endl '\n'

// Set up : Global Variables
int M, N;
int A[500][500];
int dp[500][500];
int dy[4] = {-1, 0, 0, +1};
int dx[4] = {0, -1, +1, 0};

// Set up : Functions Declaration
bool isValid(int y, int x);
int f(int cy, int cx);


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

    // Set up : Input
    cin >> M >> N;
    for (int i=0; i<M; i++)
        for (int j=0; j<N; j++)
            cin >> A[i][j];

    // Process
    /* dp[i][j] = (0,0) -> (i,j) 내리막길 경로의 개수 */
    memset(dp, -1, sizeof(dp));
    dp[0][0] = 1; /* 제일 왼쪽 위 칸 시작점(0,0)의 dp 초기화 */
    int ans = f(M-1, N-1); /* (0,0) -> (M-1,N-1) 내리막길 경로의 개수 */

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
bool isValid(int y, int x)
/* 주어진 좌표(y,x)가 유효하면 true를 반환 그 외 false 를 반환 */
{
    return y >= 0 && y < M && x >= 0 && x < N;
}

int f(int cy, int cx)
/* dp[i][j] 에 (0,0) -> (i,j) 내리막길 경로의 개수를 저장 및 반환 */
{
    if (dp[cy][cx] != -1) return dp[cy][cx];
    dp[cy][cx] = 0;
    for (int i=0; i<4; i++) {
        int ay = cy + dy[i];
        int ax = cx + dx[i];
        /* 인접한 칸들의 높이가 현재 칸들의 높이보다 높아야만
         * 인접한 칸으로 부터 현재 칸으로 오는 내리막 길이 존재할 수 있음 */
        if (isValid(ay, ax) && A[ay][ax] > A[cy][cx]) {
            dp[cy][cx] += f(ay, ax);
        }
    } return dp[cy][cx];
}
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글