티스토리 뷰

알고리즘/BOJ

[BOJ-1520]내리막길

개발하는 후딘 2020. 3. 1. 16:43
728x90
반응형

 

 

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

 

1520번: 내리막 길

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

www.acmicpc.net


[풀이]

DP와 DFS를 활용한 문제이다.

 

도착점(M-1, N-1)에 도달할 때까지 경우의 수를 점화식으로 나타내면

DP[M-1][N-1]= DP[M-2][N-1]+ DP[M-1][N-2]

 

현위치가 (0,0) 인 시작점이라면 1을 리턴한다.

 

현위치가 (0,0)이 아닌 다른 점이라면

(1) 방문했다는 의미로, DP[y][x]=0 으로 한다.

(2) 현위치의 상/하/좌/우의 좌표(nexty, nextx)가 M행 N열 배열안의 원소인지 적절하지 먼저 확인하고(isRange 함수)

(3) 현위치의 상/하/좌/우가 현위치의 값보다 크다면 (arr[nexty][nextx] > arr[y][x])

DP[y][x]= (상)DP[y-1][x] + (하)DP[y+1][x] + (좌)DP[y][x-1] + (우)DP[y][x+1]

 

그러나 만약에 현위치(y,x)의 arr값보다 큰값을 갖는 상/하/좌/우 가 존재하지 않으면 어떻게할것인가?

그냥 현위치의 DP값을 리턴을 하면된다.

그러므로 return DP[y][x] 를 한다.

 

(4) 그래서 (3)에서 제시된 점화식을 수정하자면

DP[y][x]+= DFS(nexty, nextx)

 


[코드(.py)]

python의 경우 sys.setrecursionlimit(10**6)을 하지 않으면 런타임에러가 뜬다.

재귀할 때 유의하자.

import sys
sys.setrecursionlimit(10**6)

M,N =0,0
arr=None
dp=None

#현위치의 상/하/좌/우
dy=[-1,1,0,0]
dx=[0,0,-1,1]

def isRange(y,x):
    global M,N
    if (y>=0 and y<M) and (x>=0 and x<N):
        return True
    return False

def dfs(y,x):
    global arr, dp
    # 현위치가 출발점인가?
    if (y==0 and x==0):
        return 1
    
    # 아직 방문하지 않은 상태인가?
    if dp[y][x]==-1:
        dp[y][x]=0 #현위치를 방문하고..
        
        for i in range(4):
            nexty=dy[i]+y
            nextx=dx[i]+x
            #현위치의 상/하/좌/우 가 적절한 범위에 있는가?
            if isRange(nexty, nextx):
                #현위치의 상/하/좌/우가 현위치의 값보다 큰가?
                if arr[nexty][nextx]>arr[y][x]:
                    dp[y][x]+=dfs(nexty, nextx)
                
    return dp[y][x]                    
                
    
def main():
    global M,N, arr, dp
    #M : 세로, N: 가로
    M,N = map(int, sys.stdin.readline().split())
    arr=[ list(map(int, sys.stdin.readline().split())) for _ in range(M)]
    dp=[ [-1]*N for _ in range(M)]
    result=dfs(M-1, N-1)
    print(result)
    
if __name__=='__main__':
    main()

 


[코드(.java)]

import java.util.Scanner;

public class Main{

	static int M,N;
	static int arr[][];
	static int dp[][];
	static int dy[]={-1,1,0,0};
	static int dx[]= {0,0,-1,1};
	
	public static void main(String[] args)
    {
		Scanner sc = new Scanner(System.in);
		M=sc.nextInt(); //세로크기
		N=sc.nextInt(); //가로크기
		arr=new int[M][N]; //arr선언
		dp=new int[M][N]; //dp선언
		
		for(int y=0; y<M; y++)
			for(int x=0; x<N; x++) 
            {
				arr[y][x]=sc.nextInt();
				dp[y][x]=-1;//-1로 초기화
			}		
		int result=dfs(M-1, N-1);
		System.out.println(result);
	}
	
	public static boolean isRange(int y, int x) {
		if((y>=0 && y<M)&&(x>=0 && x<N))
			return true;
		return false;
	}
	
	public static int dfs(int y, int x) {
		if(y==0 && x==0)
			return 1;
		
		//아직 방문하지 않은 상태
		if(dp[y][x]==-1) 
		{
			dp[y][x]=0;//현위치 방문
			
			//현위치 상/하/좌/우
			int nexty, nextx;
			for(int i=0; i<4; i++) 
			{
				nexty=y+dy[i];
				nextx=x+dx[i];
				if(isRange(nexty, nextx))
				{
					if(arr[nexty][nextx]>arr[y][x])
						dp[y][x]+=dfs(nexty,nextx);
				}
			}	
		}
		return dp[y][x];
	}
}

 

728x90
반응형

'알고리즘 > BOJ' 카테고리의 다른 글

[BOJ-2206] 벽부수고 이동하기  (0) 2020.03.01
[BOJ-2178] 미로탐색  (0) 2020.03.01
[BOJ-11057] 오르막수  (0) 2020.02.29
[BOJ-1463] 1로 만들기  (0) 2020.02.27
[BOJ-2747] 피보나치 수  (0) 2020.02.27
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함