https://school.programmers.co.kr/learn/courses/30/lessons/43105
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
I. 문제 개요
삼각형에 들어있는 숫자 중, 지나온 숫자들의 최대 합을 구하는 문제이다.
II. 알고리즘 설계 및 풀이
1. DP 점화식 설계
0행: 7
1행: 3 8
2행: 8 1 0
주어진 삼각형을 위와 같이 직각 삼각형으로 보자.
2행의 "8"은 1행의 "3"에서밖에 접근할 수 없다.
2행의 "1"은 1행의 "3", "8" 두 군데에서 접근할 수 있다.
2행의 "0"은 1행의 "8"에서만 접근할 수 있다.
현재 칸이 맨 처음 또는 마지막 칸이라면, 각각 바로 위, 왼쪽대각선 위의 숫자만 고려할 수 있다.
그 외의 칸이라면, 바로 위 또는 왼쪽 대각선 위의 숫자 둘 다 고려할 수 있다.
바로 위, 왼쪽 대각선 위의 숫자 중 더 큰 숫자를 택하여 현재 칸의 숫자와 더하는 방식을 통해, 원하는 최댓값을 찾을 수 있을 것이다.
if 왼쪽 끝단:
dp[i][j] = 삼각형_현재칸의_숫자 + dp_바로윗칸의_숫자
elif 오른쪽 끝단:
dp[i][j] = 삼각형_현재칸의_숫자 + dp_왼쪽대각선_위의_숫자
else:
왼쪽대각선_위의_숫자를_택한경우 = dp_왼쪽대각선_위의_숫자 + 삼각형_현재칸의_숫자
바로윗칸의_숫자를_택한경우 = dp_바로윗칸의_숫자 + 삼각형_현재칸의_숫자
dp[i][j] = max(왼쪽대각선_위의_숫자를_택한경우, 바로윗칸의_숫자를_택한경우)
위의 알고리즘을 의사코드로 표현하면 위와 같다.
이재 이를 코드로 구현하면 된다.
2. 변수 초기화
n = len(triangle)
dp = [[0] * len(triangle[i]) for i in range(n)] # triangle 모양 따라 만들기
# dp 초기화
dp[0][0] = triangle[0][0]
dp[1][0] = triangle[1][0] + dp[0][0]
dp[1][1] = triangle[1][1] + dp[0][0]
탐색에 사용할 dp를 생성하고, 초기화한다.
dp의 1행에 들어있는 각 숫자에, 0행의 숫자를 더해준다.
그 이유는 dp에서 1행의 경우, 0행에 들어있는 숫자 1개만 받을 수 있기 때문이다.
3. DP 적용
for i in range(2, n):
for j in range(0, i+1):
if j == 0: # 왼쪽 끝
dp[i][j] = triangle[i][j] + dp[i-1][j]
elif j == i: # 오른쪽 끝
dp[i][j] = triangle[i][j] + dp[i-1][j-1]
else: # 그 외
from_above = dp[i-1][j] + triangle[i][j] # 바로 위에서 넘어오는 경우
from_left = dp[i-1][j-1] + triangle[i][j] # 좌대각선 위에서 넘어오는 경우
dp[i][j] = max(from_above, from_left) # 둘 중 큰 값을 dp에 반영
ans = max(dp[-1])
return ans
dp의 2행부터 탐색을 시작한다.
j번째 숫자가 왼쪽 끝에 있다면, dp에서 바로 윗 행에 들어있는 숫자를 더해준다.
오른쪽 끝이라면, dp에서 왼쪽 대각선 위에 있는 숫자를 더해준다.
둘 다 아니라면, dp의 왼쪽 대각선 위에 있는 숫자와 현재칸의 숫자를 더한 값, 바로 윗 행의 숫자와 현재 숫자를 더한 수 중 더 큰 값을 dp에 집어넣는다.
최종적인 답안은 맨 끝 행에 들어있는 수 중, 가장 큰 수이다.
III. 전체 코드
def solution(triangle):
# 2. 변수 초기화
n = len(triangle)
dp = [[0] * len(triangle[i]) for i in range(n)] # triangle 모양 따라 만들기
# dp 초기화
dp[0][0] = triangle[0][0]
dp[1][0] = triangle[1][0] + dp[0][0]
dp[1][1] = triangle[1][1] + dp[0][0]
# 3. DP 적용
for i in range(2, n):
for j in range(0, i+1):
if j == 0: # 왼쪽 끝
dp[i][j] = triangle[i][j] + dp[i-1][j]
elif j == i: # 오른쪽 끝
dp[i][j] = triangle[i][j] + dp[i-1][j-1]
else: # 그 외
from_above = dp[i-1][j] + triangle[i][j] # 바로 위에서 넘어오는 경우
from_left = dp[i-1][j-1] + triangle[i][j] # 좌대각선 위에서 넘어오는 경우
dp[i][j] = max(from_above, from_left) # 둘 중 큰 값을 dp에 반영
ans = max(dp[-1])
return ans
IV. 풀이 결과
'CodingTest' 카테고리의 다른 글
213. House Robber II (0) | 2024.05.04 |
---|---|
등굣길 (0) | 2024.04.30 |
N으로 표현 (0) | 2024.04.20 |
의상 (0) | 2024.04.18 |
전화번호 목록 (0) | 2024.04.17 |