Algorithm/백준

[백준] 1890 - 점프

비번변경 2024. 4. 9. 16:34

문제

문제 : https://www.acmicpc.net/problem/1890

각 칸에 수가 적힌 N * N 크기의 게임판이 있다. 게임의 목표는 가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 점프하여 이동하는 것이다.

각 칸에 적힌 수는 현재 칸에서 갈 수 있는 거리를 뜻한다. 단, 0은 종착점을 의미한다. 오른쪽이나 아래쪽으로만 이동할 수 있고, 한 번 점프하는 중간에 방향을 바꿀 수 없다.

가장 왼쪽 위 칸에서 가장 오른쪽 아래 칸으로 규칙에 맞게 이동할 수 있는 경로의 수를 구하여라.

 

 

접근

2024.04.08 - [백준] 11048 - 이동하기와 비슷한 문제인데, '이동하기'는 한 번에 한 칸씩 움직이는 반면 '점프'는 이동할 수 있는 칸의 수가 정해져 있지 않다.

때문에 현재 위치한 방을 어떻게 왔는지가 아니라, 현재 위치한 방에서 도착할 수 있는 방이 어딘지 고려해야 한다. 

'이동하기' 문제와 동일하게 동적 계획법을 활용했고, 테이블에는 각 칸에 도달할 수 있는 경로의 수를 저장했다.

 

 

풀이

1. 게임판 크기 입력

N = int(sys.stdin.readline())

 

2. 게임판 입력

game = [list(map(int, sys.stdin.readline().strip().split())) for i in range(N)]

 

3. 테이블 초기화

테이블에는 각 칸에 도달할 수 있는 칸의 수를 저장할 수 있도록 0으로 초기화한다.

dp = [[0 for _ in range(N)] for _ in range(N)]

 

4. 테이블 업데이트

게임 시작 시 가장 왼쪽 위칸에서 시작한다. 이 칸은 시작하면서 도착한 것과 같으므로 1로 업데이트한다.

for i in range(N):
    for j in range(N):
        # 게임판 시작
        if i == 0 and j == 0:
            dp[i][j] = 1

그리고 현재 칸에서 도착할 수 있는 칸의 좌표를 업데이트한다. 다른 칸에 도착하기 위해서는 현재 좌표의 칸에 도착한 적이 있어야 하고, 현재 좌표의 칸이 종착점이 아니어야 한다.

if dp[i][j] > 0 and game[i][j] > 0:
    # 이동한 좌표 확인
    if i + game[i][j] < N:
        # 테이블 업데이트
        dp[i + game[i][j]][j] += dp[i][j]
    if j + game[i][j] < N:
        dp[i][j + game[i][j]] += dp[i][j]

현재 좌표가 다른 칸으로 갈 수 있는 좌표라면 오른쪽 방향으로 이동한다. 이동할 때는 이동한 후의 좌표가 게임판 밖으로 나가지 않도록 해야 한다. 그리고 저장하는 값은 현재 좌표 칸에 도달할 수 있는 경로의 수화 이동한 후의 좌표에 도달할 수 있던 경로의 수의 합으로 한다.

그리고 아래쪽도 동일하게 처리한다.

 

5. 결괏값 출력

테이블에서 종착지 좌표의 값을 출력한다.

print(dp[-1][-1])

 

전체 소스는 다음과 같다.

import sys

N = int(sys.stdin.readline())
game = [list(map(int, sys.stdin.readline().strip().split())) for i in range(N)]
dp = [[0 for _ in range(N)] for _ in range(N)]

for i in range(N):
    for j in range(N):
        # 게임판 시작
        if i == 0 and j == 0:
            dp[i][j] = 1

        if dp[i][j] > 0 and game[i][j] > 0:
            if i + game[i][j] < N:
                dp[i + game[i][j]][j] += dp[i][j]
            if j + game[i][j] < N:
                dp[i][j + game[i][j]] += dp[i][j]
print(dp[-1][-1])

 

 

참고 문서

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

https://yabmoons.tistory.com/116