[DP] 백준 #1149 RGB 거리 - Python

2025. 1. 16. 23:34· Algorithm/Baekjoon
목차
  1. 🗂️ 문제
  2. 💡 접근법
  3. 😎 내 코드
  4. 👀 배운 코드
  5. 🧐 배운 점
  6. ✅ 정답 확인

🗂️ 문제

링크: https://www.acmicpc.net/problem/1149

 

💡 접근법

모든 집에 대해 비용을 적은 것부터 많은 것으로 정렬한 뒤, 비용이 적은 집에 대해서 우선적으로 처리하는 방식이다.

즉, 현재 순간에서 가장 비용이 적은 것을 선택한다.

 

이때 문제에서 제시한 바와 같이, 이전 집과는 같은 색을 칠하지 않는 조건을 처리한다.

 

😎 내 코드

import sys
from collections import deque

N = int(sys.stdin.readline())

house_cost = []
RGB = ["R", "G", "B"]
for i in range(N):
    costs = list(map(int, sys.stdin.readline().split()))
    for c, r in zip(costs, RGB):
        house_cost.append((i+1, c, r))  # (집 번호, 비용, 색상)

house_cost.sort(key=lambda x: x[1])
house_cost = deque(house_cost)

complete_house = [()] * (N+1)

cost = house_cost.popleft()
complete_house[cost[0]] = cost

while house_cost:
    cost = house_cost.popleft()
    house_num = cost[0]
    used_color = []

    if complete_house[house_num] == ():  # 아직 칠하지 않은 집
        if house_num == 1:  # 1번 집인 경우
            if complete_house[2] != ():  # 2번째 집이 칠해진 경우 used_color 리스트에 추가
                used_color.append(complete_house[2][2])
        elif house_num == N:  # N번 집인 경우
            if complete_house[N-1] != ():  # N-1번째 집이 칠해진 경우 used_color 리스트에 추가
                used_color.append(complete_house[N-1][2])
        else:  # i(2 ≤ i ≤ N-1)번 집인 경우
            if complete_house[house_num-1] != ():  # i-1번 집이 칠해진 경우
                used_color.append(complete_house[house_num-1][2])
            if complete_house[house_num+1] != ():  # i+1번 집이 칠해진 경우
                used_color.append(complete_house[house_num+1][2])
    
        if cost[2] not in used_color:
            complete_house[cost[0]] = cost

total = 0
for i in range(1, N+1):
    total += complete_house[i][1]
print(total)

하지만 그리디(즉, 비용이 작은 것을 우선 선택하는 방식)는 현재 순간의 선택만을 최적화한다.

이 문제에서는 이후 선택이 앞선 선택에 의해 영향을 받기 때문에, 전체적으로는 최적의 해를 보장하지 못한다.

 

따라서 DP로 해결해야 한다.

 

👀 배운 코드

import sys

N = int(sys.stdin.readline())
arr = [list(map(int, sys.stdin.readline().split())) for _ in range(N)]

dp = [[0] * 3 for _ in range(N)]
dp[0] = arr[0]

for i in range(1, N):
    dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + arr[i][0]
    dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + arr[i][1]
    dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + arr[i][2]

print(min(dp[N-1]))

먼저, DP 조건에 맞는지 확인해 보면,

 

1) 큰 문제를 작은 문제로 쪼갤 수 있는가?

그렇다. N행까지 모두 더한 최소 비용은 N-1행까지의 최소 비용 문제로 쪼개진다.

2) 작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일한가?

그렇다. 이전 집까지 최소 비용 결과에 현재 집의 값을 더해서 최소 비용을 업데이트하게 되므로 이전의 결과를 그대로 가져와서 사용한다고 볼 수 있다.

 

즉, 집에 색을 하나씩 칠하면서 누적된 최소 비용값을 dp 테이블에 저장하고, 마지막 집까지 도달했을 때 가장 작은 비용 값을 출력하면 된다. 이 규칙을 점화식으로 나타내면 **dp[i][0] = min(dp[i-1][1], dp[i-1][2])**이다.

 

🧐 배운 점

항상 dp 규칙을 찾아내는 게 어려운 것 같은데… 시간 복잡도를 계산해 보면서 어느 알고리즘일지 유추하고, DP 조건에 맞는지 확인해보는 습관을 들여야겠다.

 

✅ 정답 확인

'Algorithm > Baekjoon' 카테고리의 다른 글

[구현] 백준 #11723 집합 - Python  (0) 2025.01.19
[DFS/BFS] 백준 #1012 유기농 배추 - Python  (0) 2025.01.17
[DP] 백준 #1699 제곱수의 합 - Python  (0) 2024.07.25
[DP] 백준 #11727 2×n 타일링 2 - Python  (0) 2024.07.25
[BFS] 백준 #2468 안전 영역 - Python  (0) 2024.05.30
  1. 🗂️ 문제
  2. 💡 접근법
  3. 😎 내 코드
  4. 👀 배운 코드
  5. 🧐 배운 점
  6. ✅ 정답 확인
'Algorithm/Baekjoon' 카테고리의 다른 글
  • [구현] 백준 #11723 집합 - Python
  • [DFS/BFS] 백준 #1012 유기농 배추 - Python
  • [DP] 백준 #1699 제곱수의 합 - Python
  • [DP] 백준 #11727 2×n 타일링 2 - Python
jyjyjy25
jyjyjy25
jyjyjy25
기록하는 습관
jyjyjy25
전체
오늘
어제
  • 분류 전체보기 (148)
    • Algorithm (87)
      • Baekjoon (59)
      • Programmers (28)
    • Courses (18)
      • Java (3)
      • Spring (11)
      • JPA (4)
    • CS (7)
    • DevOps (8)
      • AWS (8)
    • Framework (10)
      • Spring (5)
      • JPA (5)
    • Security (13)
      • Web Hacking (10)
      • Dreamhack (0)
      • ISMS (3)
    • Research (1)
    • Etc (4)

인기 글

최근 글

hELLO · Designed By 정상우.v4.2.1
jyjyjy25
[DP] 백준 #1149 RGB 거리 - Python
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.