알고리즘 연습/동적 계획법

[🥈1 / 백준 11048 / 파이썬] 이동하기

김세진 2021. 9. 18. 15:20
반응형

 

 

11048번: 이동하기

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다. 준규는

www.acmicpc.net

 

문제

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다.

준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다.

준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최댓값을 구하시오.

입력

첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000)

둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다.

출력

첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.

 

예제 입력 1 

3 4
1 2 3 4
0 0 0 5
9 8 7 6

예제 출력 1 

31


예제 입력 2 

3 3
1 0 0
0 1 0
0 0 1

예제 출력 2 

3


예제 입력 3 

4 3
1 2 3
6 5 4
7 8 9
12 11 10

예제 출력 3 

47



 

풀이

 

정해진 규칙에 따라 이동할 때, 가져올 수 있는 사탕의 최댓값을 출력하는 문제이다.

 

준규는 시작점에서부터 오른쪽, 아래, 오른쪽 대각선 아래 3방향으로 움직일 수 있다.

다만, 한 번에 대각선으로 이동하는 것보다 2단계에 걸쳐 이동하는 것이 무조건 이득이므로

한 번에 대각선으로 내려가는 경우는 없다고 생각해도 무방하다.

 

메모이제이션을 위한 dp 배열을 생성한 뒤, 맨 윗줄에서부터 배열을 훑어가며 dp 배열에 합산한다.

점화식은 다음과 같다.

 

dp[i][j] = max(dp[i-1][j], dp[i][j-1])+arr[i][j]

 

인덱스를 맞춰주기 위해 0으로 이루어진 패딩 배열을 덧붙였다.

 

import sys
input = sys.stdin.readline

n,m = map(int,input().split())
arr = [[0]*(m+1)] + [[0]+list(map(int,input().split())) for i in range(n)]
dp = [[0]*(m+1) for i in range(n+1)]
for i in range(1,n+1):
    for j in range(1,m+1):
        dp[i][j] = max(dp[i-1][j],dp[i][j-1])+arr[i][j]
print(dp[n][m])
반응형