문제 소개 www.acmicpc.net/problem/4386

내용

  • n개의 별들을 이어서 별자리를 하나 만들 것이다.
  • 별자리를 이루는 선은 서로 다른 두 별을 일직선으로 이은 형태이다.
  • 모든 별들은 별자리 위의 선을 통해 서로 직/간접적으로 이어져 있어야 한다.
  • 별들이 2차원 평면 위에 놓여 있다.
  • 선을 하나 이을 때마다 두 별 사이의 거리만큼의 비용이 든다고 할 때, 별자리를 만드는 최소 비용을 구하시오.

입력

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

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

출력

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

해결 방법

아이디어

백준 2887 행성 터널 문제와 마찬가지로 최소 비용 스패닝 트리 문제이다.

백준 2887 행성 터널과 달리 cost가 x축 y축 각각의 값 중 최소값이 아니므로 백준 2887 행성 터널에서 했던 각축으로 정렬 이후 바로 옆에 있는 정점끼리의 간선만 취급해서는 풀리지 않는다.

 

n이 100이다. n^2 해도 10,000 이므로 프림 혹은 크루스칼 알고리즘만 적용하면 풀릴 듯 하다.

크루스칼로 풀어보자.

실제 풀이 코드

package class5.p4386;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * 별자리 만들기
 * 2021-01-22
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int starsCount = Integer.parseInt(br.readLine());

        List<Star> stars = new ArrayList<>();
        for (int i = 0; i < starsCount; i++) {
            String[] split = br.readLine().split(" ");

            stars.add(new Star(i, Double.parseDouble(split[0]), Double.parseDouble(split[1])));
        }

        List<Edge> edges = new ArrayList<>();
        for (Star from : stars) {
            for (Star to : stars) {
                edges.add(new Edge(from.index, to.index, from.calcCost(to)));
            }
        }

        Collections.sort(edges);

        int[] cycleTable = new int[starsCount];

        for (int i = 0; i < starsCount; i++) {
            cycleTable[i] = i;
        }

        double answer = 0.0;
        for (Edge edge : edges) {
            int fromParent = getParent(cycleTable, edge.from);
            int toParent = getParent(cycleTable, edge.to);

            if (fromParent != toParent){
                union(cycleTable, fromParent, toParent);
                answer += edge.cost;
            }
        }

        System.out.printf("%.2f", answer);
    }

    private static void union(int[] cycleTable, int from, int to) {
        int fromParent = getParent(cycleTable, from);
        int toParent = getParent(cycleTable, to);
        if (fromParent > toParent) cycleTable[fromParent] = toParent;
        else cycleTable[toParent] = fromParent;
    }

    private static int getParent(int[] cycleTable, int from) {
        if (cycleTable[from] == from) return from;
        return getParent(cycleTable, cycleTable[from]);
    }

    static class Star {
        int index;
        double x;
        double y;

        public Star(int index, double x, double y) {
            this.index = index;
            this.x = x;
            this.y = y;
        }

        public double calcCost(Star other) {
            return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
        }
    }

    static class Edge implements Comparable<Edge>{
        int from;
        int to;
        double cost;

        public Edge(int from, int to, double cost) {
            this.from = from;
            this.to = to;
            this.cost = cost;
        }

        @Override
        public int compareTo(Edge o) {
            return Double.compare(this.cost, o.cost);
        }
    }
}

결과

'알고리즘 문제 > 백준' 카테고리의 다른 글

백준 10775 공항 java  (0) 2021.02.01
백준 9466 텀 프로젝트 java  (0) 2021.01.27
백준 9252 LCS 2 java  (0) 2021.01.25
백준 7453 합이 0인 네자리 수 java  (0) 2021.01.23
백준 2887 행성 터널 java  (0) 2021.01.21

BELATED ARTICLES

more