본문 바로가기
카테고리 없음

[G3] 백준 1520 - 내리막 (Python3)

by JJong | 쫑 2025. 3. 10.

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


💡 해결방법

DFS + DP메모제이션

DFS 만으로 풀면 시간초과or메모리초과

DP 만으로 풀면 메모리초과


처음엔 상하좌우가 아니라 [좌,우,아래]로만 움직일 수 있는 줄 알고 O(N^3) 풀이를 준비했던,,

 

(0,0)에서 (r-1, c-1) 위치로 이동하는 경우의 수를 구하는 문제이다.

이동 조건은 상하좌우 다 되고, 대신 grid의 현재위치의 높이가 이동하려는 위치의 높이보다 높아야 된다.


처음 접근했던 방법이다.

목적지(10)에서 목적지로 가는 방법은 0개라고 가정하고, 목적지에서 상하좌우에 자기 높이보다 높은 숫자로 이동하면서 {현재 방법 + 1}로 두는 방법으로 접근을 했다. 하지만 결국 그냥 dfs로 푸는 것과 별 차이가 없었다.


 

아싸리 그냥 이번엔 dfs로 완전 가보자. 하고 그린 그림이다.

막상 그림을 그리다보니 32에서 20과 30에서 한 번씩 거쳐가는 상황을 잘 표현할 수 있겠다 싶었다.

그 방법이 dp 테이블을 이용한 것이다.

생각난 김에 밑에 코드도 후다닥 썼다.

물론 recursion 하려는 좌표가 범위 안에 들어오는지, 이미 탐색한 곳인지, 더 높은 숫자 아닌지 등 따질 것이 있다.

 

이렇게 핵심 아이디어를 접하고 코드로 구현했다.


🧾코드

# 1520 내리막길
import sys
sys.setrecursionlimit(10**5)

r, c = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(r)]

#북 동 남 서
dy, dx = [-1, 0, 1, 0], [0, 1, 0, -1]
dp = [[-1]*c for _ in range(r)]

def DFS(y, x):
    if y == r-1 and x == c-1:
        return 1
    if dp[y][x] != -1:
        return dp[y][x]
    
    dp[y][x] = 0
    for i in range(4):
        ny, nx = y+dy[i], x+dx[i]
        if 0<=ny<r and 0<=nx<c and grid[ny][nx] < grid[y][x]:
            dp[y][x] += DFS(ny, nx)
    return dp[y][x]
    
print(DFS(0, 0))

코드 설명

    if dp[y][x] != -1:
        return dp[y][x]

이미 탐색을 완료한 경우라면 그냥 그 위치에서 이동 경우의 수를 바로 가져온다. (굳이 똑같은 길로 탐색을 할 필요가 없다)

댓글