개발자 톡

연습문제 톡 나무 수확

DP로 푼 코드 + 해설 공유합니다 (파이썬)

등록일
2024-03-29 23:26:34
조회수
108
작성자
s000715

다른 분들의 연습문제 톡을 구경하던 도중 DP이지만 저와 다른 방식으로 해결하신 분의 풀이 방법을 보고 배워 가는 내용이 많아서 제가 푼 방법도 공유해 봅니다!


문제를 처음 접했을 때는 2차원 DP 배열을 만들어서 dp[i][j][0]에는 (i, j)번째 칸까지의 최대 수확량을, dp[i][j][1]에는 (i, j)번째 칸까지 수로를 넣은 경로 중 가장 큰 값을 집어넣으려고 했습니다. 하지만 스프링클러를 사용하기 전 수확량이 최대인 경로라고 하더라도, 스프링클러를 사용한 후 수확량이 최대가 아닌 경우가 발생합니다. 예를 들어

4

1 3 5 7

9 1 1 1

1 1 1 1

로 입력값이 주어진 경우, 스프링클러를 사용하지 않았을 때 최대 수확량은 (1+3+5+7+1+1) = 18입니다. 그러나 스프링클러를 사용했을 때 최대 수확량은 (1+18+1+1+1+1) = 23이 됩니다. 따라서 이 방식으로 dp배열을 관리하면 오답을 받습니다.


제가 푼 방식은 2차원 DP 배열을 만들고,

dp[i][j][0]에는 (i, j)번째 칸까지 스프링클러를 사용하지 않은 경우 최대 수확량을,

dp[i][j][1]에는 (i, j)번째 칸까지 스프링클러를 사용한 경우 최대 수확량을 넣어줬습니다.


이때 dp[i][j][1]에는

(i-1, j) 또는 (i, j-1)번째 칸까지 스프링클러를 사용하지 않은 경우 + (현재 칸의 수확량 * 2) 와

(i-1, j) 또는 (i, j-1)번째 칸까지 스프링클러를 사용한 경우 + (현재 칸의 수확량 *1)

중 큰 값이 들어갑니다.


정답을 받은 코드도 함께 첨부합니다!

제 코드에서 이해가 되지 않는 부분이나 개선할 점이 있다면 댓글 남겨주세요!


import sys
input = sys.stdin.readline


N = int(input())
graph = [list(map(int, input().split())) for _ in range(N)]
dp = [[[0, 0] for _ in range(N)] for _ in range(N)]


for i in range(N):
    for j in range(N):
        up = 0 if not i else dp[i-1][j][0]
        left = 0 if not j else dp[i][j-1][0]
        dp[i][j][0] = max(up, left) + graph[i][j]
        umax = 0 if not i else max(dp[i-1][j][1] + graph[i][j], dp[i-1][j][0] + graph[i][j] * 2)
        lmax = 0 if not j else max(dp[i][j-1][1] + graph[i][j], dp[i][j-1][0] + graph[i][j] * 2)
        dp[i][j][1] = max(umax, lmax, 2*graph[i][j])
print(dp[N-1][N-1][1])
#나무_수확

이 카테고리의 톡 더보기