파이썬 정수 삼각형(백준 BOJ 1932)


문제

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

위 그림은 크기가 5인 정수 삼각형의 한 모습이다.

맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다.

삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다.


입력

첫째 줄에 삼각형의 크기 n(1 ≤ n ≤ 500)이 주어지고, 둘째 줄부터 n+1번째 줄까지 정수 삼각형이 주어진다.


출력

첫째 줄에 합이 최대가 되는 경로에 있는 수의 합을 출력한다.


예제 입력 1

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

예제 출력 1

30


📝 풀어보기

📌 아래로 내려가는 삼각형은 크게 3가지로 구분된다.

  1. 누적되는 열이 0번째일 때
  2. 누적되는 열이 끝일 때
  3. 누적되는 열이 양쪽으로 갈라질 때

이 3가지의 계산을 누적해서 저장한 뒤에 제일 큰 값을 출력하면 된다.


📌 삼각형의 크기 n을 입력받고, 누적값을 저장할 리스트 dp를 생성한다.

n만큼 반복하면서 dp에 삼각형의 값을 리스트 형태로 저장받는다.

n = int(input())
dp = []

for i in range(n) :                           
    dp.append(list(map(int,input().split())))


📌 삼각형의 행과 열을 기준으로 2중 리스트를 순회하면서

  1. j==0(순회하는 열이 0) 일때 0번째 열끼리 값을 누적시킨다.
  2. j==i(순회하는 열이 마지막) 일때 마지막 열끼리 값을 누적시킨다.
  3. 양갈래로 뻗어나갈 때 dp[i-1][j-1], dp[i-1][j] (왼쪽과 오른쪽) 중 큰 값을 누적한다.

마지막으로 전부 누적된 n-1행에서의 최대값을 출력하면 최대가 있는 경로의 합을 구할 수 있다.

for i in range(1,n) : # 행을 기준으로 1, 2, 3, 4, 5
    for j in range(0,i+1) : # 열을 기준으로 0, 1, 2, 3, 4, 5, 6
        if j == 0 : # 순회하는 열이 0일때 
            dp[i][0] += dp[i-1][0] # 0열끼리 더하기 
        elif j == i : # 순회하는 열이 끝일때 
            dp[i][j] += dp[i-1][j-1] # 마지막 열끼리 더하기 
        else : # 양갈래로 뻗어나갈때
            dp[i][j] += max(dp[i-1][j-1],dp[i-1][j]) # 두 화살표중 더 큰 경우 누적하기

print(max(dp[n-1])) # n-1행에서의 최댓값 출력


전체 코드

# 5 
# 7 dp[0][0]
# 3 8 dp[1][0], dp[1][1]
# 8 1 0 dp[2][0], dp[2][1], dp[2][2]
# 2 7 4 4 dp[3][0], dp[3][1], dp[3][2], dp[3][3]
# 4 5 2 6 5 dp[4][0], dp[4][1], dp[4][2], dp[4][3], dp[4][4]

n = int(input())
dp = []

for i in range(n) :                           
    dp.append(list(map(int,input().split())))

for i in range(1,n) : # 행을 기준으로 1, 2, 3, 4, 5
    for j in range(0,i+1) : # 열을 기준으로 0, 1, 2, 3, 4, 5, 6
        if j == 0 : # 순회하는 열이 0일때 
            dp[i][0] += dp[i-1][0] # 0열끼리 더하기 
        elif j == i : # 순회하는 열이 끝일때 
            dp[i][j] += dp[i-1][j-1] # 마지막 열끼리 더하기 
        else : # 양갈래로 뻗어나갈때
            dp[i][j] += max(dp[i-1][j-1],dp[i-1][j]) # 두 화살표중 더 큰 경우 누적하기

print(max(dp[n-1])) # n-1행에서의 최댓값 출력

관심있을 포스팅