백준 1520 - 내리막 길
Updated:
Java
1520 번 - 내리막 길
문제
여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다.
한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다.
현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다.
그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지점까지 가고자 한다. 위와 같은 지도에서는 다음과 같은 세 가지 경로가 가능하다.
지도가 주어질 때 이와 같이 제일 왼쪽 위 지점에서 출발하여 제일 오른쪽 아래 지점까지 항상 내리막길로만 이동하는 경로의 개수를 구하는 프로그램을 작성하시오.
접근 방법
DFS를 사용하면 0,0에서 시작하여 n-1, m-1까지 도착하는 개수의 수가 즉 경로의 개수이다.
하지만, 단순하게 DFS를 사용하면 시간초과가 나므로, DP를 이용하여 시간을 단축한다.
DP의 방법은, 이미 방문한 지점을 다른 경로가 그 지점을 방문하려 할 때, 방문하는 것 대신 현재 그 지점의 경로의 개수를 받아오는 것이다.
위는 간단한 예제이다.
노란 선의 경로로 목표인 1 지점까지 이동하였으면, 해당 지점의 DP값은 1이다.
이후 초록 선의 경로가 1 지점에 도달하려했지만, 해당 지점은 이미 방문 하였으므로, 해당 DP값을 리턴한다.
해당 DP는 1이므로 1 + 1로 경로는 총 2개가 된다.
위를 반복하면, 0,0 시작점에는 각 경로들이 리턴되며 그것들의 합이 총 경로의 수가 된다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result;
static long cnt = 0;
static int[][] map, dp;
static boolean[][] vis;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
map = new int[n][m];
dp = new int[n][m];
for(int i = 0; i < n; i++) {
stk = new StringTokenizer(br.readLine());
for(int j = 0; j < m; j++) {
map[i][j] = stoi(stk.nextToken());
dp[i][j] = -1; // 초기 상태는 -1로 한다.
}
}
System.out.println(dfs(0,0));
br.close();
}
// 하, 우, 상, 좌
static int[] dy = {1,0,-1,0};
static int[] dx = {0,1,0,-1};
static int dfs(int y, int x) {
if(y == n - 1 && x == m - 1) {
return 1;
}
// 이미 한번 방문한 지점이면 해당 값을 리턴하고 종료한다.
if(dp[y][x] != -1)
return dp[y][x];
dp[y][x] = 0;
int ny,nx;
for(int i = 0; i < 4; i++) {
ny = y + dy[i];
nx = x + dx[i];
if(isIn(ny,nx) && map[y][x] > map[ny][nx]) {
dp[y][x] += dfs(ny,nx); // 경로 수를 추가한다.
}
}
return dp[y][x];
}
// 주어진 범위 안에 있는가
public static boolean isIn(int y, int x){
if(y < 0 || y >= n || x < 0 || x >= m)
return false;
return true;
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
시작점의 값으로 dp가 모이는 하향식의 문제였다.
개선할 점
없습니다.