[백준][1520번: 내리막 길]

호준·2022년 5월 12일
0

Algorithm

목록 보기
70/111
post-thumbnail

🎈문제

문제링크

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다.현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다. 그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지점까지 가고자 한다. 위와 같은 지도에서는 다음과 같은 세 가지 경로가 가능하다.지도가 주어질 때 이와 같이 제일 왼쪽 위 지점에서 출발하여 제일 오른쪽 아래 지점까지 항상 내리막길로만 이동하는 경로의 개수를 구하는 프로그램을 작성하시오.

🎈입력

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

🎈출력

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

🎈접근방법

  1. 처음에는 dfs으로 접근했는데 시간초과가 났다.
  2. dp(Dynamic Programming)을 같이 사용하여 풀었다.
  3. dfs를 돌면서 해당 위치에 도달했을 때 dp 값을 확인하여 이미 목표점까지 갔었던 위치라면 해당하는 그 값을 return한다.

🎈코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    static int N,M;
    static int[] mx = {-1,1,0,0};
    static int[] my = {0,0,-1,1};
    static int[][] map;
    static int[][] dp;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());

        map = new int[M+1][N+1];
        for(int i=1; i<=M; i++){
            st = new StringTokenizer(br.readLine());
            for(int j=1; j<=N; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        dp = new int[M+1][N+1];
        for(int i=1; i<=M; i++){
            for(int j=1; j<=N; j++){
                dp[i][j] = -1;
            }
        }

        int answer = dfs(1,1);
        System.out.println(answer);
    }
    static int dfs(int x, int y) {
        if (x == M && y == N) {
            return 1;
        }
        if (dp[x][y] != -1) {
            return dp[x][y];
        }
        dp[x][y] = 0; // 0으로 초기화
        for (int i = 0; i < 4; i++) {
            int px = x + mx[i];
            int py = y + my[i];
            if (px > 0 && py > 0 && px <= M && py <= N) {
                if (map[x][y] > map[px][py]) { // 내리막길일 때
                    dp[x][y] += dfs(px, py);
                }
            }
        }
        return dp[x][y];
    }
}
profile
도전하자

0개의 댓글