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

 

1149번: RGB거리

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나

www.acmicpc.net


문제 해결을 위한 과정

이 문제 역시 전형적인 dp 즉 다이내믹 프로그래밍으로 해결할 수 있는 문제였습니다.

이해하기 쉽게 그림으로 그리면 다음과 같습니다. 간략하게 예시 1에 대해서 살펴봅시다.

먼저 3행 3열 이면서 int(1e9)으로 이루어진 이차원 리스트 dp는 다음과 같습니다.

 

그 후 0행에 예제의 정보들을 넣어주면 다음과 같습니다.

그 후 같은 열을 제외한 값을 더한 후 min값을 넣어주면 다음과 같습니다.

0행 1열에 대해서는 다음과 같습니다.

이러한 방식에 대해서 반복해나가면 쉽게 해결할 수 있습니다. 


소스코드 - python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
= int(input())
data = []
for _ in range(n):
  a, b, c = map(int, input().split())
  data.append((a, b, c))
 
dp = [[int(1e9)] * 3 for _ in range(n)]
a, b, c = data[0]
dp[0][0= a; dp[0][1= b; dp[0][2= c
 
for i in range(n-1):
  for j in range(3):
    for k in range(3):
      if j == k:
        continue
      else:
        dp[i+1][k] = min(dp[i+1][k], dp[i][j]+data[i+1][k])
 
print(min(dp[n-1]))
cs

소스코드 - c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
#define MAX 1001
using namespace std;
 
int main(void) {
  int n;
  scanf("%d"&n);
 
  int house[MAX][3];
  for(int i = 0; i < n; i++) {
    for (int j = 0; j < 3; j++) {
      scanf("%d"&house[i][j]);
    }
  }
 
  long long dp[MAX][3];
 
  fill(&dp[0][0], &dp[MAX-1][3], 1e9);
  dp[0][0= house[0][0];
  dp[0][1= house[0][1];
  dp[0][2= house[0][2];
 
  for(int i = 0; i < n-1; i++) {
    for (int j = 0; j < 3; j++) {
      for (int k = 0; k < 3; k++) {
        if (j == k)
          continue;
        else
          dp[i+1][k] = min(dp[i+1][k], dp[i][j] + house[i+1][k]);
      }
    }
  }
 
  long long minValue = 1e9;
  for (int i = 0; i < 3; i++) {
    if(minValue > dp[n-1][i])
      minValue = dp[n-1][i];
  }
  printf("%lld", minValue);
  return 0;
}
cs

위의 코드는 언뜻보면 O(n^3)인 것처럼 보이지만 사실상 두 번째, 세 번째 루프가 3까지 반복하므로 시간 복잡도가 O(n^3)이 아닌 것을 알 수 있습니다. 따라서 시간 초과 판정을 받지 않고 해결할 수 있습니다.

 

+ Recent posts