<백준>1890번 점프

ming·2023년 4월 3일

백준1890번 링크

문제

N×N 게임판에 수가 적혀져 있다. 이 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프를 해서 가는 것이다.

각 칸에 적혀있는 수는 현재 칸에서 갈 수 있는 거리를 의미한다. 반드시 오른쪽이나 아래쪽으로만 이동해야 한다. 0은 더 이상 진행을 막는 종착점이며, 항상 현재 칸에 적혀있는 수만큼 오른쪽이나 아래로 가야 한다. 한 번 점프를 할 때, 방향을 바꾸면 안 된다. 즉, 한 칸에서 오른쪽으로 점프를 하거나, 아래로 점프를 하는 두 경우만 존재한다.

가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 이동할 수 있는 경로의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장 오른쪽 아래 칸에는 항상 0이 주어진다.

출력

가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 문제의 규칙에 맞게 갈 수 있는 경로의 개수를 출력한다. 경로의 개수는 263-1보다 작거나 같다.

예제

풀이

DP문제이다.
문제에서 주어진 내용을 보면 게임의 점프 진행은 언제나 왼쪽->오른쪽, 위쪽->아래쪽으로 진행된다.
하여 DP의 진행 또한 왼쪽에서 오른쪽으로, 위쪽에서 아래쪽으로 진행을 하면 문제를 풀 수 있다.

DP의 각각의 위치에는 말이 시작점에서 점프되어 온 경우의 수를 가지고 있다.
예제를 통해 문제를 풀면 맨 처음 움직일 수 있는 (1, 1)(가장 왼쪽의 가장 위쪽)은 어떤 게임이 되어도 1이 되어야 한다.
해당 부분은 시작점이므로 무조건 해당 부분에서 이동이 일어나기 때문이다.
아래처럼 DP가 준비된다.

1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

그다음은 (1, 1) 위치에서 DP[1][1]만큼 오른쪽과 아래쪽으로 이동된 곳은 출발 지점의 수만큼 증가하게 된다.

※ 출발 지점의 수만큼 증가시키는 이유는 출발 지점의 DP가 3인 경우는 해당 출발지점까지 오는 경우의 수가 3가지 이므로 해당 출발 점에서 다음 위치로 이등 가능한 경우의 수 또한 3가지 존재하기 때문이다.

DP는 아래처럼 된다.

dp
1010
0000
1000
0000

이제 DP를 왼쪽에서 오른쪽으로 위쪽에서 아래쪽으로 반복하면서 0이 아닌 경우와 범위 안에 있는 경우 점프를 또 진행한다.

DP가 0인 경우는 해당 위치는 최초 시작점에서 점프하여 올 수 없다 는것을 의미하므로 처리가 필요 없다.

2번의 점프를 진행하면 DP는 아래처럼 된다.

dp
1010
0000
1100
1010

3번의 점프를 진행하면 DP는 아래처럼 된다.

dp
1010
0000
1101
1012

4번의 점프를 진행하면 DP는 아래처럼 된다.

dp
1010
0000
1101
1013

코드

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        int num = Integer.parseInt(br.readLine());
        long[][] dp = new long[num+1][num+1];
        dp[1][1] = 1;
        for (int i = 1; i <= num ; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= num ; j++) {
                int moveValue = Integer.parseInt(st.nextToken());
                
                if(dp[i][j] >= 1 && moveValue != 0){
                    if (i + moveValue <= num){
                        dp[i + moveValue][j] += dp[i][j];
                    }
                    if (j + moveValue <= num){
                        dp[i][j + moveValue] += dp[i][j];
                    }
                }
            }
        }
        System.out.println(dp[num][num]);
    }
}
profile
개발 성장 기록

0개의 댓글