Skip to content

Commit

Permalink
✍️ create: baekjoon 17404
Browse files Browse the repository at this point in the history
- 백준 17404번 문제 해설
  • Loading branch information
marunemo committed Dec 19, 2023
1 parent 3f2b928 commit 6a4c97c
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 56 deletions.
Binary file modified assets/screenshots/b1402.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshots/b17404.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 0 additions & 56 deletions code/b17404.cpp

This file was deleted.

164 changes: 164 additions & 0 deletions pps/b17404.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
title: 백준 17404 | RGB거리 2
level: GOLD IV
layout: default
parent: 문제 풀이
---
{% assign title = page.title | split: " | " %}
{% assign name = title[0] %}
{% assign title = title[1] %}
{% assign number = name | split: " " %}
{% assign number = number[1] %}

# **{{ title }}**
{: .no_toc .fs-9 }

{{ name }}
{: .fs-4 .d-inline }

{% if page.level contains 'BRONZE' %}
{{ page.level }}
{: .label .label-bronze }
{% elsif page.level contains 'SILVER' %}
{{ page.level }}
{: .label .label-silver }
{% elsif page.level contains 'GOLD' %}
{{ page.level }}
{: .label .label-gold }
{% elsif page.level contains 'PLATINUM' %}
{{ page.level }}
{: .label .label-platinum }
{% endif %}

<br/>

1. TOC
{:toc}

---

## 문제 내용
{: .fw-700 }

![problem.png](../assets/screenshots/b{{ number }}.png)

#### [문제 링크](https://www.acmicpc.net/problem/{{ number }})
{: .no_toc .fs-4 }

## 해결 방안
{: .fw-700 }

<div class="code-example" markdown="1">
총 N개의 집에 빨강, 초록, 혹은 파랑 3가지 색 중에 하나의 색을 칠해야한다.
각각의 집은 자신의 앞뒤에 있는 집과 색이 달라야 한다.
예로 들어, 8번째 집은 7번째 집과 9번째 집과의 색이 달라야 한다.
추가적으로, 1번째 집과 맨 마지막 집인 N번째 집은 서로 색이 달라야 한다.
때문에 1번째 집은 2번째와 N번째, N번째 집은 (N-1)번째와 1번째 집과 색이 서로 달라야 한다.
각 집에 빨강이나 초록, 파랑 3가지 색을 칠하는 각각의 비용이 있으며,
문제에서 요구하는 바는 규칙에 따라 N개의 집에 모두 색을 칠했을 때의 드는 비용의 최솟값이다.
{: .mb-1 }

우선, 각 집은 자신의 이전에 있는 집과 다음에 있는 집의 색이 달라야 하는 조건을 점화식으로 생각해보자.
i번째 집에 (i-1)번째 집과 (i+1)번째 집과 다른 색이 칠해져 있다고 한다면,
(i+1)번째 집을 기준으로 보면 이미 i번째에는 다른 색이 칠해져 있는 것이므로 (i+2)번째 색만 고려하면 된다.
다시 말해, 임의의 집과 그 다음 집에서의 색이 다르다는 것은 그 다음 집에서 이전 집과 색이 다르다는 것과 동치라는 것이다.
때문에 **각 집에 대하여 이전 집과 다른 색을 칠하기만 한다면, 임의의 집은 항상 자신의 앞뒤의 집과 다른 색을 가지는 규칙을 만족한다**.
{: .my-1 }

그 다음에는 1번째 집과 N번째 집과의 관계만 고려하면 된다.
인접한 집들은 자신의 이전 집과의 관계만 고려하면 되지만, 1번째와 N번째는 각각의 경우의 수를 모두 고려하는 수 밖에 없다.
1번째 집이 빨강일 때에는 N번째 집은 초록이나 파랑이어야 하고, 파랑일 때는 N번째 집은 빨강과 초록이어야 한다.
정리하자면,
**각각 빨강, 파랑, 초록에서 시작한 집의 경우에는 N번째 집이 빨강, 파랑, 초록인 경우 중 시작한 집의 색깔을 제외한 경우의 최솟값을 찾으면 문제의 해답이 된다**.
{: .my-1 }

이제 문제를 푸는 알고리즘에 대해 알아보자.
먼저, 첫 번째 집을 빨강, 파랑, 초록으로 칠하는 경우를 각각 구분지어야 한다.
두번째 집부터 N번째 집까지는 현재 칠하려는 색과 이전에 칠해진 색을 비교하며,
이전 집에서 현재 칠하려는 색과 다른 두 색을 칠한 경우 중 총 비용이 더 적게 든 쪽을 고른다.
N번째 집까지 이 과정을 반복한 후, 첫 번째 집과 N번째 집의 색이 다른 경우 중 최솟값을 찾으면 된다.
{: .mt-1 }
</div>

## 풀이 코드
{: .fw-700 }

```cpp
#include <iostream>
#include <vector>
#define MAX_VALUE 10000

using namespace std;

int main() {
// Fast IO
cin.tie(0);
cout.tie(0);
ios_base::sync_with_stdio(false);

int n; // 집의 개수
long rgb[3]; // 각 집에서의 빨강, 초록, 파랑으로 칠하는 비용

// 1번째 집을 빨강으로 칠했을 때의 각 집에서의 빨강, 초록, 파랑으로 칠하는 최소 비용
vector<int> rStart(3, MAX_VALUE);
// 1번째 집을 초록으로 칠했을 때의 각 집에서의 빨강, 초록, 파랑으로 칠하는 최소 비용
vector<int> gStart(3, MAX_VALUE);
// 1번째 집을 파랑으로 칠했을 때의 각 집에서의 빨강, 초록, 파랑으로 칠하는 최소 비용
vector<int> bStart(3, MAX_VALUE);
// 각각의 칠하는 최소 비용은 처음에는 최댓값으로 시작함

// 이전 집을 빨강, 초록, 파랑으로 칠했을 경우에 대한 각각의 총 비용
vector<int> preValue(3);
// 1번째 집을 빨강, 초록, 파랑으로 칠했을 때의 N번째 집에 대한 최소 비용
int minCost[3];

cin >> n;
for(int i = 0; i < n; i++) {
// 각 집을 빨강, 초록, 파랑으로 칠하는 비용 입력
cin >> rgb[0] >> rgb[1] >> rgb[2];

// 맨 처음 입력의 경우에는 각각 1번째 집에 칠하는 색깔의 비용만 고려한다.
if(i == 0) {
rStart[0] = rgb[0];
gStart[1] = rgb[1];
bStart[2] = rgb[2];
}
// 2번째부터는 현재 칠하려는 색깔과 이전 집에서 다른 색을 칠한 경우만 고려하고,
// 그 중 최솟값을 골라 현재 칠하려는 색깔과 합한다.
else {
// 1번째 집이 빨강일 경우에 대한 반복
preValue = rStart;
rStart[0] = min(preValue[1], preValue[2]) + rgb[0];
rStart[1] = min(preValue[0], preValue[2]) + rgb[1];
rStart[2] = min(preValue[0], preValue[1]) + rgb[2];
// 1번째 집이 초록일 경우에 대한 반복
preValue = gStart;
gStart[0] = min(preValue[1], preValue[2]) + rgb[0];
gStart[1] = min(preValue[0], preValue[2]) + rgb[1];
gStart[2] = min(preValue[0], preValue[1]) + rgb[2];
// 1번째 집이 파랑일 경우에 대한 반복
preValue = bStart;
bStart[0] = min(preValue[1], preValue[2]) + rgb[0];
bStart[1] = min(preValue[0], preValue[2]) + rgb[1];
bStart[2] = min(preValue[0], preValue[1]) + rgb[2];
}
}

// 1번째 집이 빨강인 경우, 마지막 집이 초록이나 파랑인 경우 중 최솟값을 취한다.
minCost[0] = min(rStart[1], rStart[2]);
// 1번째 집이 초록인 경우, 마지막 집이 빨강이나 파랑인 경우 중 최솟값을 취한다.
minCost[1] = min(gStart[0], gStart[2]);
// 1번째 집이 파랑인 경우, 마지막 집이 빨강이나 초록인 경우 중 최솟값을 취한다.
minCost[2] = min(bStart[0], bStart[1]);

// 1번째 집이 빨강, 초록, 파랑인 3가지 경우 중 최솟값을 찾는다.
minCost[0] = min(minCost[0], minCost[1]);
minCost[0] = min(minCost[0], minCost[2]);

cout << minCost[0] << endl;
return 0;
}
```
{: .lh-0 .fw-700 .fs-4 }

0 comments on commit 6a4c97c

Please sign in to comment.