문제
준규는 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)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.
예제 입력 13 41 2 3 4 0 0 0 5 9 8 7 6 |
예제 출력 131 |
예제 입력 23 31 0 0 0 1 0 0 0 1 |
예제 출력 23 |
예제 입력 34 31 2 3 6 5 4 7 8 9 12 11 10 |
예제 출력 347 |
풀이
정해진 규칙에 따라 이동할 때, 가져올 수 있는 사탕의 최댓값을 출력하는 문제이다.
준규는 시작점에서부터 오른쪽, 아래, 오른쪽 대각선 아래 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])
'알고리즘 연습 > 동적 계획법' 카테고리의 다른 글
[🥈1 / 백준 1309 / 파이썬] 동물원 (0) | 2021.09.28 |
---|---|
[🥈2 / 백준 1890 / 파이썬] 점프 (0) | 2021.09.18 |
[🥈1 / 백준 2133 / 파이썬] 타일 채우기 (0) | 2021.08.24 |
[🥈2 / 백준 15988 / 파이썬] 1, 2, 3 더하기 3 (0) | 2021.08.23 |
[🥈1 / 백준 11052 / 파이썬] 카드 구매하기 (0) | 2021.08.22 |