백준 온라인 저지, 다이나믹프로그래밍 / 1520번: 내리막길 (파이썬 / 백준 골드문제)

2021. 9. 1. 01:01알고리즘/다이나믹프로그래밍

728x90
반응형

문제

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

문제 정의

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다.

현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다. 그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지점까지 가고자 한다. 위와 같은 지도에서는 다음과 같은 세 가지 경로가 가능하다.
  
지도가 주어질 때 이와 같이 제일 왼쪽 위 지점에서 출발하여 제일 오른쪽 아래 지점까지 항상 내리막길로만 이동하는 경로의 개수를 구하는 프로그램을 작성하시오.


입력

첫째 줄에는 지도의 세로의 크기 M과 가로의 크기 N이 빈칸을 사이에 두고 주어진다. 이어 다음 M개 줄에 걸쳐 한 줄에 N개씩 위에서부터 차례로 각 지점의 높이가 빈 칸을 사이에 두고 주어진다. M과 N은 각각 500이하의 자연수이고, 각 지점의 높이는 10000이하의 자연수이다.


출력

첫째 줄에 이동 가능한 경로의 수 H를 출력한다. 모든 입력에 대하여 H는 10억 이하의 음이 아닌 정수이다.


예제 입력 1

4 5
50 45 37 32 30
35 50 40 20 25
30 30 25 17 28
27 24 22 15 10

예제 출력 1

3

접근 방법

- DFS와 BFS의 경우
- - 만약 DFS나 BFS를 통해 탐색을 할 경우 러프하게 시간복잡도를 고려했을 때 4의 250000제곱만큼 연산을 하기 때문에 실패할 가능성이 크다.
- - 더군다나 메모리 제한이 128mb이기 때문에 메모리 초과가능성도 높다.

코드

# https://www.acmicpc.net/problem/1520
# 접근방법
# DFS와 BFS의 경우
# - 만약 DFS나 BFS를 통해 탐색을 할 경우 러프하게 시간복잡도를 고려했을 때 4의 250000제곱만큼 연산을 하기 때문에 실패할 가능성이 크다.
# - 더군다나 메모리 제한이 128mb이기 때문에 메모리 초과가능성도 높다.

# 0. 주어진 지도를 입력받고, 지도의 크기만큼 dp테이블을 0으로 초기화한다. 단, 시작위치인 0, 0은 1응 저장한다.
# 1. 가장 오른쪽 아래에서부터 탐색을 시작해 상하좌우의 지역 중 현재 위치보다 높은 곳을 탐색한다.
# 2. 상하좌우 중 현재 위치보다 높은 곳의 dp값이 있다면 해당 값을 모두 더한 값을 현재 위치에 저장한다.
# 3. 상하좌우 중 현재 위치보다 높은 곳의 dp값이 없다면 해당 위치에서 재탐색하며 위의 과정을 반복한다.
# 4. 모든 탐색이 끝난 뒤, 해당 값을 출력한다.
import sys
sys.setrecursionlimit(10**5)
m, n = map(int, sys.stdin.readline().split())
map_ = [list(map(int, sys.stdin.readline().split())) for _ in range(m)]
dp = [[-1 for _ in range(n)] for _ in range(m)]
dp[0][0] = 1

def dfs(row, col):
    if dp[row][col] >= 0:
        return dp[row][col]

    count = 0
    for dr, dc in [[1, 0], [-1, 0], [0, 1], [0, -1]]:
        if 0<=row+dr<=m-1 and 0<=col+dc<=n-1 and map_[row][col] < map_[row+dr][col+dc]:
            count += dfs(row+dr, col+dc)
    dp[row][col] = count
    return dp[row][col]
    
dfs(m-1, n-1)
print(dp[m-1][n-1])
728x90
반응형