문제 설명

위와 같은 삼각형의 꼭대기에서 바닥까지 이어지는 경로 중, 거쳐간 숫자의 합이 가장 큰 경우를 찾아보려고 합니다. 아래 칸으로 이동할 때는 대각선 방향으로 한 칸 오른쪽 또는 왼쪽으로만 이동 가능합니다. 예를 들어 3에서는 그 아래칸의 8 또는 1로만 이동이 가능합니다.
삼각형의 정보가 담긴 배열 triangle이 매개변수로 주어질 때, 거쳐간 숫자의 최댓값을 return 하도록 solution 함수를 완성하세요.
제한사항
삼각형의 높이는 1 이상 500 이하입니다.
삼각형을 이루고 있는 숫자는 0 이상 9,999 이하의 정수입니다.
입출력 예
triangle result
[[7], [3, 8], [8, 1, 0], [2, 7, 4, 4], [4, 5, 2, 6, 5]] 30
다이나믹 프로그래밍은 메모리 공간을 약간 더 사용해서 연산 속도를 비약적으로 증가시키는 방법이다. 우선 다음과 같은 2가지 조건을 만족할 때 다이나믹 프로그래밍을 사용할 수 있다.
큰 문제를 작은 문제로 나눌 수 있다.
작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일하다.
dp는 top-down 방식과 bottom-up방식이 있다.
d = [0] * 100
d[1] = 1 # 첫 번째 항
d[2] = 1 # 두 번째 항
N = 99 # 피보나치 수열의 99번째 숫자는?
for i in range(3, N+1):
d[i] = d[i-1] + d[i-2]
print(d[N])
위와 같은 방식은 작은 문제부터 차근차근 답을 도출해서 큰 문제를 해결한다고 하여 Bottom-Up 방식이라고 한다.
재귀함수를 사용하는 Top-Down 방식을 사용하다 보면 재귀 횟수 제한 오류가 걸릴 수도 있기 때문에 bottom-up 방식을 사용할 것을 권한다.
따라서 위의 문제를 bottom-up 방식을 이용해서 푼다면,
맨 밑의 [4, 5, 2, 6, 5]부터 시작하여
n번째 줄의 i번째 원소 = max(n+1번째 줄의 i번째 원소, n+1번째 줄의 i+1번째 원소) + n번째 줄의 i번째 원소
dp[n][i] = max(dp[n+1][i], dp[n+1][i+1]) + triangle[n][i]
위와 같은 방식으로 구할 수 있다.

(이해를 돕기 위한 그림 설명)
def solution(triangle):
dp = [triangle[-1]]
for i in range(len(triangle)-2,-1,-1):
dp.append([])
for j in range(len(triangle[i])):
dp[-1].append(max(dp[-2][j], dp[-2][j+1])+triangle[i][j])
return dp[-1][0]
