n
: 삼각형의 크기 ()
integer
: 삼각형 이루는 각 정수 ()
맨 위층부터 맨 아래층에 도달할 때까지 선택된 수의 합이 최대가 되는 경로를 구하는 문제이다.
각 층을 거쳐 얻은 선택된 수의 합은 이전 층에서 얻은 최댓값에서 현재 층의 최댓값을 더함으로써 얻을 수 있다.
→ 이전에 풀었던 문제 땅따먹기와 유사하게 DP로 해결할 수 있다.
예제 입력1을 예로 들었을 때 배열이 다음과 같다.
|7|
|3|8|
|8|1|0|
|2|7|4|4|
|4|5|2|6|5|
아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 오른쪽에 있는 것만 선택 가능하므로
4층의 8은 7만, 3층의 1은 3 또는 8, 2층의 7은 8 또는 1을 선택할 수 있다.
→ 아래 있는 수는 자신의 왼쪽 위나 바로 위의 숫자 중 더 큰 수를 고를 수 있다.
즉, dp[i][j] += max(dp[i-1][j-1], dp[i-1][j])
가 된다.
하지만 정수 삼각형이므로 배열의 범위가 벗어나지 않는지 확인하는 부분이 필요하다.
j=0
이면 += dp[i-1][j]
j=len(triangle[i])
이면(맨 끝이면) += dp[i-1][j-1]
+= max(dp[i-1][j-1], dp[i-1][j])
조건에 따라 점화식을 반복하여 dp 테이블을 채운다면 마지막 칸에서 원하는 최댓값을 구할 수 있다.
입력 →
DP로 테이블 채우기 →
최종 시간복잡도
최악일 때 이 되는데 이는 제한시간 2초 내 충분히 수행 가능하다.
IndexError
가 발생했다.j == len(triangle[i])
라고 했는데 인덱스는 -1
해주어야 하는 것을 잊었다.import sys
input = sys.stdin.readline
# 입력
n = int(input())
triangle = [list(map(int, input().split())) for _ in range(n)]
# DP 계산
for i in range(1, n):
for j in range(len(triangle[i])):
# 맨 왼쪽일 경우 바로 위만 받음
if j == 0:
triangle[i][j] += triangle[i-1][j]
# 맨 오른쪽일 경우 왼쪽 위만 받음
elif j == len(triangle[i]) - 1:
triangle[i][j] += triangle[i-1][j-1]
# 그외엔 바로 위, 왼쪽 위 둘다 받음
else:
triangle[i][j] += max(triangle[i-1][j-1], triangle[i-1][j])
# 출력
print(max(triangle[-1]))