Algorithm 문제/BOJ

[c++] BOJ 1149번 :: RGB거리

희은w 2020. 4. 16. 21:31

RGB 거리

μ‹œκ°„ μ œν•œ λ©”λͺ¨λ¦¬ μ œν•œ 제좜 μ •λ‹΅ λ§žμ€ μ‚¬λžŒ μ •λ‹΅ λΉ„μœ¨
0.5 초 (μΆ”κ°€ μ‹œκ°„ μ—†μŒ) 128 MB 42269 19789 14882 47.682%

문제

RGBκ±°λ¦¬μ—λŠ” 집이 N개 μžˆλ‹€. κ±°λ¦¬λŠ” μ„ λΆ„μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 있고, 1번 μ§‘λΆ€ν„° N번 집이 μˆœμ„œλŒ€λ‘œ μžˆλ‹€.

집은 λΉ¨κ°•, 초둝, νŒŒλž‘ 쀑 ν•˜λ‚˜μ˜ μƒ‰μœΌλ‘œ μΉ ν•΄μ•Ό ν•œλ‹€. 각각의 집을 λΉ¨κ°•, 초둝, νŒŒλž‘μœΌλ‘œ μΉ ν•˜λŠ” λΉ„μš©μ΄ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ•„λž˜ κ·œμΉ™μ„ λ§Œμ‘±ν•˜λ©΄μ„œ λͺ¨λ“  집을 μΉ ν•˜λŠ” λΉ„μš©μ˜ μ΅œμ†Ÿκ°’μ„ κ΅¬ν•΄λ³΄μž.

  • 1번 μ§‘μ˜ 색은 2번 μ§‘μ˜ 색과 κ°™μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.
  • N번 μ§‘μ˜ 색은 N-1번 μ§‘μ˜ 색과 κ°™μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.
  • i(2 ≤ i ≤ N-1)번 μ§‘μ˜ 색은 i-1번, i+1번 μ§‘μ˜ 색과 κ°™μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.

μž…λ ₯

첫째 쀄에 μ§‘μ˜ 수 N(2 ≤ N ≤ 1,000)이 μ£Όμ–΄μ§„λ‹€. λ‘˜μ§Έ 쀄뢀터 N개의 μ€„μ—λŠ” 각 집을 λΉ¨κ°•, 초둝, νŒŒλž‘μœΌλ‘œ μΉ ν•˜λŠ” λΉ„μš©μ΄ 1번 μ§‘λΆ€ν„° ν•œ 쀄에 ν•˜λ‚˜μ”© μ£Όμ–΄μ§„λ‹€. 집을 μΉ ν•˜λŠ” λΉ„μš©μ€ 1,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

좜λ ₯

첫째 쀄에 λͺ¨λ“  집을 μΉ ν•˜λŠ” λΉ„μš©μ˜ μ΅œμ†Ÿκ°’μ„ 좜λ ₯ν•œλ‹€.

μ•Œκ³ λ¦¬μ¦˜ λΆ„λ₯˜

  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°

λ‚˜μ˜ λ‹΅

μƒκ°μ˜ 흐름
  1. 완전탐색이 κ°€λŠ₯ν•œκ°€?

    2^(N) => 2^(1000)의 μ‹œκ°„μ΄ 걸리기 λ•Œλ¬Έμ— λΆˆκ°€λŠ₯ν•˜λ‹€.

    심지어 μ‹œκ°„μ œν•œμ΄ 0.5μ΄ˆμ΄λ‹€.

  2. 각 λ‹¨κ³„λ³„λ‘œ 생각 κ°€λŠ₯ν•œκ°€? (졜적 λΆ€λΆ„ ꡬ쑰인가?)

    ν•œ 단계가 λ‹€μŒ 단계듀에 영ν–₯을 λ―ΈμΉœλ‹€.

    심지어 μ–΄λ””κΉŒμ§€ 영ν–₯을 λ―ΈμΉœλ‹€λŠ” 것 없이 μ΄ν›„μ˜ λͺ¨λ“  단계에 영ν–₯을 λ―ΈμΉœλ‹€.

ex_)

μ§‘1 μ§‘2 μ§‘3 μ§‘4
1 9 100 1000
2 8 101 1001
3 1 7 1

 μ΄λ ‡κ²Œ μž…λ ₯이 듀어왔을 λ•Œ, μ§‘1κ³Ό μ§‘2둜만 보면 λ”ν•΄μ„œ κ°€μž₯ μž‘μ€ μˆ˜κ°€ λ‚˜μ˜€λŠ” (1,1)을 택해야할 것이닀. ν•˜μ§€λ§Œ μ§‘3κΉŒμ§€ 보면 (1,8,7)이 κ°€μž₯ μž‘μ€ 수의 집합이닀. λ”°λΌμ„œ μ§‘1의 선택은 μ§‘3의 선택과 독립적이지 μ•Šλ‹€.

μ΄μ–΄μ„œ μ§‘4κΉŒμ§€ λ³΄μ•˜μ„ λ•ŒλŠ” (1,1,100,1)으둜 바뀐닀. κ²°κ΅­ νŠΉμ •ν•œ indexκΉŒμ§€μ˜ 졜적의 닡이 μ΄ν›„μ˜ 졜적의 닡을 ν™•μ‹ μ‹œν‚¬ 순 μ—†λ‹€.

 κ·Έλ ‡λ‹€λ©΄ 완전탐색은 λ„ˆλ¬΄ 였래걸리고, 단계 λ³„λ‘œ μͺΌκ°œμ„œ λ³Ό μˆ˜λ„ μ—†λŠ”λ° μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒ?

μ–΄μ¨Œλ“  ν•œ λ‹¨κ³„μ˜ 선택이 λͺ¨λ“  단계에 영ν–₯을 λ―ΈμΉ˜λŠ” 거라면 μ§‘1λΆ€ν„° μ§‘NκΉŒμ§€ RGB쀑 ν•˜λ‚˜λ₯Ό νƒν•˜λŠ” λͺ¨λ“  경우의 수λ₯Ό 생각해야할 것이닀. ν•˜μ§€λ§Œ 완전탐색을 ν•˜λ˜ μ‹œκ°„μ„ μ€„μ΄λŠ” 방법을 μ°Ύμ•„λ³΄μž.

이럴 λ•ŒλŠ” λŒ€λΆ€λΆ„ μ‹œκ°„μ„ μ–»κΈ°μœ„ν•΄ 곡간을 μ’€ μ‚¬μš©ν•˜λ©΄ λœλ‹€.

μš°μ„  μ™„μ „ 탐색일 λ•Œμ˜ 선택을 트리둜 λ‚˜νƒ€λ‚΄λ³΄λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

 μ§‘1의 선택을 μš°μ„  1둜 κ³ μ •μ‹œμΌ°μ„ λ•Œ μ΄λŸ¬ν•œ νŠΈλ¦¬κ°€ μ€„μ§€μ–΄μ„œ λ‚˜μ˜¨λ‹€. νŠΈλ¦¬λŠ” μ§‘μ˜ 갯수 N만큼 μ•„λž˜λ‘œ λ»—μ–΄ 높이가 N이 될 것이며, 높이가 1μ”© λ”ν•΄μ§ˆ λ•Œλ§ˆλ‹€ λ…Έλ“œμ˜ κ°―μˆ˜λŠ” 2배둜 μ¦κ°€ν•˜κ²Œ 될 것이닀. 이런 트리λ₯Ό binary tree라고 ν•œλ‹€.

완전탐색은 이와같이 binary treeκ°€ λ‚˜μ˜€κ²Œ λ˜λŠ”λ°, μ§‘1의 선택은 3κ°€μ§€κ°€ κ°€λŠ₯ν•˜λ―€λ‘œ 전체 경우의 μˆ˜λŠ” 3*2^(N)-1이닀. λ”°λΌμ„œ μ‹œκ°„ 내에 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μ–΄λ ΅λ‹€.

 λ‹€λ§Œ μœ„μ˜ κ·Έλ¦Όμ—μ„œ μ§‘3의 선택이 1둜 κ²ΉμΉ˜λŠ” κ±Έ λ³Ό 수 μžˆλ‹€. κ·Έλ ‡λ‹€λ©΄ 이λ₯Ό λ¬Άμ–΄μ„œ λ‹€μŒκ³Ό 같이 ν‘œν˜„ν•  수 μžˆλ‹€.

 

 μ΄λ ‡κ²Œ 겹친 λΆ€λΆ„μ˜ 계산은 ν•œλ²ˆλ§Œ ν•˜λŠ” μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜λŠ” 것이 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ΄λ‹€.

즉, 이 λ¬Έμ œλŠ” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ΄μ§€λ§Œ μ΅œμ λΆ€λΆ„κ΅¬μ‘°λ₯Ό κ°€μ§€κ³  μžˆμ§€λŠ” μ•Šμ€ λ¬Έμ œμ΄λ‹€.

λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ€ 이 값이 이미 κ³„μ‚°λ˜μ—ˆμŒμ„ μ–΄λ–»κ²Œ μ•Œ 수 μžˆμ„κΉŒ? λ₯Ό κ³ λ―Όν•΄μ•Όν•˜λŠ”λ°, 본인은 κ·Έλƒ₯ λ©”λͺ¨λ¦¬λ₯Ό μ“°κ³  vector둜 μ €λ§ŒνΌμ˜ 배열을 λ§Œλ“€κΈ°λ‘œ ν–ˆλ‹€.

 λ³ΈμΈμ€ memorizeν•˜λŠ” ν•¨μˆ˜λ₯Ό λ”°λ‘œ μ“°λ©΄μ„œ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μ „κ°œν•˜μ§€ μ•Šκ³  μ• μ΄ˆμ— 묢인 트리의 ꡬ쑰둜 자료ꡬ쑰λ₯Ό λ§Œλ“€μ—ˆλ‹€.

 κ° λ‹¨κ³„λ§ˆλ‹€ 1μ”© λ…Έλ“œμ˜ μˆ˜κ°€ λŠ˜μ–΄λ‚˜κ³  1λΆ€ν„° NκΉŒμ§€μ˜ 집이 μžˆμœΌλ―€λ‘œ N(N-1)/2 만큼의 μ €μž₯곡간이 ν•„μš”ν•˜λ‹€. N의 μ΅œλŒ€λŠ” 1,000μ΄λ―€λ‘œ N^2이라고 해도 10^6μ΄λ‹ˆ int ν˜•(4byte)λ₯Ό μ €μž₯ν•  λ•Œ 4*10^6byte = 4MB 정도 μ‚¬μš©λœλ‹€.

예제

 

μœ„μ—μ„œ μ†Œκ°œν•œ μ˜ˆμ œμ—μ„œ μ§‘1의 선택을 3으둜 κ³ μ •ν–ˆμ„ λ•Œλ₯Ό μ‚΄νŽ΄λ³΄μž. λ‹€μŒκ³Ό 같은 νŠΈλ¦¬κ°€ λ§Œλ“€μ–΄μ§„λ‹€.

 

맨 μ•„λž˜ λ…Έλ“œλΆ€ν„° μ˜¬λΌμ˜€λ©΄μ„œ 두 개의 κ°’ 쀑 μž‘μ€ 값을 μœ„μ˜ λ…Έλ“œ 값에 더해쀀닀. 이λ₯Ό λ°˜λ³΅ν•˜λ©΄

 

이런 νŠΈλ¦¬κ°€ λ‚˜μ˜€λŠ”λ°, 맨 μœ„μ˜ λ…Έλ“œκ°’ 112κ°€ μ§‘1의 값이 3일 λ•Œ λ‚˜μ˜¬ 수 μžˆλŠ” μ΅œμ†Œμ˜ 값이닀.

이런 μ‹μœΌλ‘œ μ§‘1의 값이 1일 λ•Œ, 2일 λ•Œ λͺ¨λ‘ μ§„ν–‰ν•œ ν›„ 3κ°€μ§€ κ°’ 쀑 κ°€μž₯ μž‘μ€ 값을 좜λ ₯ν•˜λ©΄ λœλ‹€.

μ½”λ“œ

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int RGB[1000][3];
int N;

int calMin(int first_num) {

    vector<int> arr[1000];
    for (int i = N-1; i >= 0; i--) {
        int plus_num = first_num;
        int j = i+1;
        while (j--) {
            int index = (plus_num++ + i) % 3;
            arr[i].push_back(RGB[i][index]);
        }
        first_num = (first_num+2)%3+1;
    }

    vector<int> result[1000];
    vector<int>::iterator iter;
    for (int i = N-1; i >= 1; i--) {
        for (int j = 0; j < arr[i].size()-1; j++) {
            arr[i - 1][j] += min(arr[i][j], arr[i][j+1]);
        }
    }
    return arr[0][0];
}

int main() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < 3; j++) {
            cin >> RGB[i][j];
        }
    }

    int result=1e9;
    for (int i = 0; i <= 2; i++) {
        result = min(result, calMin(i));
    }

    cout << result;
}

ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€

4
1 2 3
9 8 1
100 101 7
1000 1001 1
103
4
1 2 3
100 101 7
9 8 1
1000 1001 1
17

λ‹€λ₯Έ λ‹΅

μ΄λ ‡κ²Œ λ³΅μž‘ν•˜κ²Œ ν•  ν•„μš” 없이 ν•œ μ§‘μ”© λ°›μ•„μ˜€λ©΄μ„œ 6λ²ˆμ”©λ§Œ κ³„μ‚°ν•˜λ©΄ λ˜λŠ” λ¬Έμ œμ˜€λ‹€. μ§‘1의 RGBλ₯Ό λ°›μ•„μ˜€κ³  μ§‘2의 RGBλ₯Ό λ°›μ•„μ˜¬ λ•Œ,

μ§‘2 R => μ§‘1 G or μ§‘1 B
μ§‘2 G => μ§‘1 R or μ§‘1 B
μ§‘3 B => μ§‘1 R or μ§‘1 G

μ΄λ ‡κ²Œ 6번만 κ³„μ‚°ν•΄μ„œ 각 κ²½μš°μ— μ΅œμ†Œκ°’μ„ μ €μž₯ν•˜κ³  계속 μ§„ν–‰ν•˜λ©΄ λœλ‹€.

μ΄λŠ” μœ„μ— ν‘œμ‹œν•œ 트리 λͺ¨μ–‘을 거꾸둜 μ˜¬λΌκ°€λŠ” 것이닀.

λ°˜μ‘ν˜•