Lv3. 정수 삼각형 ( Python )


Lv3. 정수삼각형

# 문제 설명

스크린샷 2018-09-14 오후 5.44.19.png

위와 같은 삼각형의 꼭대기에서 바닥까지 이어지는 경로 중, 거쳐간 숫자의 합이 가장 큰 경우를 찾아보려고 합니다. 아래 칸으로 이동할 때는 대각선 방향으로 한 칸 오른쪽 또는 왼쪽으로만 이동 가능합니다. 예를 들어 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


문제 해결 시 고려사항

  • Dynamic Programming, 점화식을 이용한 문제해결

본 문제는 DP를 이용한 문제 해결이 가능하다. 문제 해결에서 유의해야 할 점은 이 전 상태를 이용하여 새로운 상태를 만들어나가는 것인데, 본 문제에서 사용해야하는 이전 상태에 해당하는 자료는 현재 줄(행)의 윗 줄(행)의 원소들이다.

우선 dp의 첫 줄에 대해서는 dp 작업의 필요 없으니 주어지는 triangle의 첫 줄의 값을 할당한다.

 dp = []
     dp.append(triangle[0])

이 후에는, 두 번째 줄부터 윗 줄의 정보를 사용하여 dp를 채워나간다.

윗 줄의 원소를 이용할 때 고려해야 할 조건은 다음과 같은 3가지가 존재한다.

  1. 현재 줄의 가장 좌측 dp를 만드는 경우
  2. 현재 줄의 가장 우측 dp를 만드는 경우
  3. 이 외, 즉 사이에 위치한 dp를 만드는 경우

위의 고려사항들을 고려하여 아래와 같이 반복문을 작성한다.

 # 두 번재 줄부터 위의 숫자 중 해당 위치로 올 수 있는 수와의 합 중 최대치를 dp에 저장
     for i in range(1, len(triangle)):
         tmp = []
         for j in range(len(triangle[i])):
             # 해당 줄의 가장 좌측 원소일 경우 => 같은 열의 윗줄의 원소와의 합
             if j==0:
                 tmp.append(triangle[i][j] + dp[i-1][0])
             # 해당 줄의 가장 우측 원소일 경우 => 현재 열 - 1의 윗줄의 원소와의 합
             elif j==len(triangle[i])-1:
                 tmp.append(triangle[i][j] + dp[i-1][len(triangle[i-1])-1])
             # 이 외의 경우 => 윗 줄의 -1 열과 동일 열 중 큰 수와의 합
             else:
                 tmp.append(triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]))
         # 해당 줄(행)에 대한 dp 추가
         dp.append(tmp)

위와 같은 작업이 모두 끝나면 전체에 대한 dp 작성이 완료되는데, 이 문제에서는 거쳐간 숫자의 최댓값을 return하라고 명시되어 있으니 dp의 가장 아랫줄 중 최댓값을 return 한다.

 # 마지막 행의 최대값 반환
     return max(dp[len(triangle)-1])


Imgur

Imgur

N이 3인 경우

Imgur

Imgur

Imgur

위와 같은 정보를 최종 정리하여 아래와 같이 작성하였다.

 tile = [0,1,2]
   for  i in range(3,n+1):
       tile.append(tile[i-2] % 1000000007 + tile[i-1] % 1000000007)
   return tile[n] % 1000000007



전체 코드

def solution(triangle):
    dp = []
    dp.append(triangle[0])
    # 두 번재 줄부터 위의 숫자 중 해당 위치로 올 수 있는 수와의 합 중 최대치를 dp에 저장
    for i in range(1, len(triangle)):
        tmp = []
        for j in range(len(triangle[i])):
            # 해당 줄의 가장 좌측 원소일 경우 => 같은 열의 윗줄의 원소와의 합
            if j==0:
                tmp.append(triangle[i][j] + dp[i-1][0])
            # 해당 줄의 가장 우측 원소일 경우 => 현재 열 - 1의 윗줄의 원소와의 합
            elif j==len(triangle[i])-1:
                tmp.append(triangle[i][j] + dp[i-1][len(triangle[i-1])-1])
            # 이 외의 경우 => 윗 줄의 -1 열과 동일 열 중 큰 수와의 합
            else:
                tmp.append(triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]))
        # 해당 줄(행)에 대한 dp 추가
        dp.append(tmp)
    # 마지막 행의 최대값 반환
    return max(dp[len(triangle)-1])