ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 4386번 별자리 만들기
    문제 풀이 2020. 8. 22. 17:44

    4386 별자리 만들기


    문제


    도현이는 우주의 신이다. 이제 도현이는 아무렇게나 널브러져 있는 n개의 별들을 이어서 별자리를 하나 만들 것다. 별자리의 조건은 다음과 같다

    -별자리를 이루는 선은 서로 다른 두 별을 일직선으로 이은 형태이다.

    -모든 별들은 별자리 위의 선을 통해 서로 직/간접적으로 이어져 있어야 한다.

    별들이 2차원 평면 위에 놓여 있다. 선을 하나 이을 때마다 두 별 사이의 거리만큼의 비용이 든다고 할 때, 별자리를 만드는 최소 비용을 구하시오.


    입력


    첫째 줄에 별의 개수 n이 주어진다. (1 ≤ n ≤ 100)

    둘째 줄부터 n개의 줄에 걸쳐 각 별의 x, y좌표가 실수 형태로 주어지며, 최대 소수점 둘째자리까지 주어진다. 좌표는 1000을 넘지 않는 양의 실수이다.


    출력


    첫째 줄에 정답을 출력한다. 절대/상대 오차는 10-2까지 허용한다.



    풀이)

    모든 별들은 이어져 있어야 하며, 별들을 이을 때 최소 비용을 구하는 문제이므로 MST를 구현하면 되는 문제다.


    MST는 Kruskal algorithm을 이용해서 구현했다.


    과정

    1. 별들의 좌표들을 모두 저장해둔다.

    2. 저장해둔 별들의 위치를 이용해, 각 별마다 다른 별들과의 거리를 저장해둔다.


       거리 공식: 

       공식구하기 쉽게 <cmath>라이브러리를 이용한다.

       제곱근 함수는 sqrt(x) : x의 제곱근을 return

       제곱함수는 pow(x,y) : x^y를 return


    3. 별들끼리의 거리를 저장한 배열을 거리 비용을 기준으로 오름차순으로 정렬한다.

    4. 가장 비용이 적은 거리부터 하나씩 살펴보며 별들을 이어준다.

       (별들이 이미 이어졌는지는 Union-find를 이용해 확인해주면 된다.)



    코드)


    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    using namespace std;
     
    int n;
    int parent[101];
    int s[101];
     
    struct Edge {
        int v1, v2;
        double dist;
        Edge(int v1, int v2, double dist) {
            this->v1 = v1;
            this->v2 = v2;
            this->dist = dist;
        }
        bool operator < (const Edge &a) {
            return dist < a.dist;
        }
    };
    vector<pair<doubledouble>> star;
    vector<Edge> e;
     
    int Find(int a) {
        if (a == parent[a]) return a;
        return parent[a] = Find(parent[a]);
    }
    int main() {
        
        scanf("%d"&n);
     
        double a, b;
        for (int i = 0; i < n; i++) {
            scanf("%lf %lf"&a, &b);
            star.push_back({ a,b });
            parent[i] = i;
            s[i] = 1;
        }
        for (int i = 0; i < star.size(); i++) {
            for (int j = i+1; j < star.size(); j++) {
                double x = star[i].first - star[j].first;
                double y = star[i].second - star[j].second;
                double diff = (double)sqrt((double)pow(x, 2+ (double)pow(y, 2));
                e.push_back({ i,j,diff });
            }
        }
        double result = 0;
        sort(e.begin(), e.end());
        for (int i = 0; i < e.size(); i++) {
            int v1 = Find(e[i].v1);
            int v2 = Find(e[i].v2);
            if (v1 == v2) continue;
            if (s[v1] < s[v2]) swap(v1, v2);
            parent[v2] = v1;
            s[v1] += s[v2];
            result += e[i].dist;
        }
        printf("%.2lf", result);
        return 0;
    }
    cs


    '문제 풀이' 카테고리의 다른 글

    [백준] 3665번 최종순위  (0) 2020.08.25
    [백준] 1949번 우수마을  (0) 2020.08.23
    [백준] 1197번 최소 스패닝 트리  (0) 2020.08.22
    [백준] 1717번 집합의 표현  (0) 2020.08.21
    [백준] 2263번 트리의 순회  (0) 2020.08.20

    댓글

Designed by Tistory.