개발/algorithm

[백준 1520번] 내리막길 - python

zzi_on2 2022. 5. 6. 17:01

문제 링크

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

 

1520번: 내리막 길

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

www.acmicpc.net

 

풀이 

- 처음엔 재귀를 사용해서 풀었는데 시간 초과가 발생하였다. 

# 시간 초과 발생 
import sys
sys.setrecursionlimit(10 ** 8)
input = sys.stdin.readline

def sol(x, y):
    global cnt 
    if x == m-1 and y == n-1:
        cnt += 1 
        return 
    
    if x != m-1 :
        if graph[x][y] > graph[x+1][y]:
            sol(x+1,y)
            
    if y != n-1 :
        if graph[x][y] > graph[x][y+1]:
            sol(x,y+1)
   
    if x != 0:
        if graph[x][y] > graph[x-1][y]:
            sol(x-1, y)
         
    if y != 0 :
        if graph[x][y] > graph[x][y-1]:
            sol(x,y-1)
        
        
m, n = map(int,input().split())

graph = []

for _ in range(m):
    graph.append(list(map(int,input().split())))
    
cnt = 0 
sol(0,0)
print(cnt)

- dp의 메모제이션을 사용해서 이미 경로의 수를 구한 위치에서는 다시 구하지 않고, dp에 저장된 값만 불러오도록 수정해주었다. 

import sys 
sys.setrecursionlimit(10 ** 8)
input = sys.stdin.readline

dx = [ 1, -1, 0, 0 ]
dy = [ 0, 0, 1, -1 ]

def sol(x, y):
	# 오른쪽 맨 끝 도착했으면 1 리턴 
    if x == m-1 and y == n-1:
        return 1 
    
    # 이미 방문했던 곳이면 저장된 경로의 수 바로 리턴 
    if dp[x][y] != -1:
        return dp[x][y]
        
    cnt = 0 
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        
        if 0 <= nx < m and 0 <= ny < n  and graph[x][y] > graph[nx][ny]:
            cnt += sol(nx,ny)
    
    # 경로 수 갱신     
    dp[x][y] = cnt 
    
    return dp[x][y]   
        
m, n = map(int,input().split())

graph = []
dp = [ [-1] * n for _ in range(m) ]
for _ in range(m):
    graph.append(list(map(int,input().split())))
    
print(sol(0,0))