개발/백준

백준 1932: 정수 삼각형 (Python)

센솔 2024. 3. 2. 00:23

문제

 

1932번: 정수 삼각형

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

www.acmicpc.net

 

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

맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다. 삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다.

해설

다이나믹 프로그래밍(DP)를 이용해 풀 수 있는 문제다. 위에서부터 아래로, 하향식으로 정답을 확정지어 내려가면 풀 수 있다. 발상은 어렵지 않으나 구현이 조금 까다로울 수 있다.

 

사고의 흐름은 다음과 같다.

  • 2차원 DP 테이블을 만든다. 이 테이블은 윗층부터 아래로 내려오면서 누적된 '가장 최대가 되는 숫자' 를 담고 있다.
    • 이렇게 하였을 때 최종 정답은 max(DP[n-1]) 로 구할 수 있을 것이다. 
  • 1층부터 정답을 확정하기 위해, DP[0][0]을 arr[0][0] 로 초기화한다.
  • 2층부터는 루프를 돌며 각 경우에 대해 DP를 갱신시켜간다.
    • 첫 번째 경우) 현재 숫자가 삼각형 가장 왼쪽에 있는 경우
      • 이 경우, 왼쪽 대각선은 존재하지 않는다.
      • DP 바로 윗층의 가장 왼쪽 숫자, DP[i-1][0] 을 arr[i][j]와 더하여 현재 DP에 반영한다.
    • 두 번째 경우) 현재 숫자가 삼각형 가장 오른쪽에 있는 경우
      • 이 경우 오른쪽 대각선은 존재하지 않는다
      • DP 바로 윗층의 가장 오른쪽 숫자, DP[i-1][len(DP[i-1])-1]를 arr[i][j]와 더하여 현재 DP에 반영한다.
    • 그 외의 경우)
      • 왼쪽 대각선은 DP[i-1][j-1] 로 구할 수 있다.
      • 오른쪽 대각선은 DP[i-1][j]] 로 구할 수 있다.
      • 왼쪽 대각선과 오른쪽 대각선 중, 최대가 되는 숫자를 구한 후 이를 arr[i][j]와 더하여 현재 DP에 반영한다.
  • 마지막으로 max(DP[n-1]) 로 정답을 구한다.

코드

n = int(input())
arr = [ list(map(int, input().split())) for _ in range(n)]

DP = [[] for _ in range(n)]
DP[0].append(arr[0][0])
for i in range(1, n):
    for j in range(len(arr[i])):
        if j == 0: # 제일 좌측
            DP[i].append(DP[i-1][0] + arr[i][j])
        elif j == len(arr[i])-1: # 제일 우측
            DP[i].append(DP[i-1][len(DP[i-1])-1] + arr[i][j])
        else:
            DP[i].append(max([DP[i-1][j-1], DP[i-1][j]]) + arr[i][j])
print(max(DP[n-1]))

 

'개발 > 백준' 카테고리의 다른 글

백준 1715: 카드 정렬하기 (Python)  (0) 2024.03.03
백준 12094: A와 B (Python)  (0) 2024.03.02
백준 13549: 숨바꼭질 3 (Python)  (0) 2024.02.29
백준 1305: 광고 (Python)  (0) 2024.02.25
백준 9084: 동전 (Python)  (1) 2024.01.07