일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- php 프로그래밍 입문 3판
- spring
- 자바 스프링
- 페이코 초대코드
- 자바
- 파이썬
- 페이코 추천인코드
- php 프로그래밍 입문
- 플러터 개발환경 설정
- 스프링
- programmers
- Flutter
- php 프로그래밍 입문 예제
- 플러터
- C
- Java
- php 프로그래밍 입문 문제풀이
- SWEA
- 백준
- 최단 경로
- 배열
- 페이코 친구코드
- php 프로그래밍 입문 연습문제
- 페이코 추천인
- JAVA SPRING
- C언어
- 한정 분기
- php 프로그래밍 입문 솔루션
- php
- php 프로그래밍
Archives
- Today
- Total
11-07 11:40
ImJay
[SWEA/Java] 1251. 하나로 본문
반응형
[SWEA/Java] 1251. 하나로
문제 해석
이 문제는 인도네시아의 N개 섬을 연결하는 교통 시스템을 설계하는 것이다. 각 섬은 좌표로 주어지며, 섬들을 연결하는 해저터널의 비용은 터널 길이의 제곱과 환경 부담 세율의 곱으로 계산된다. 주어진 조건 하에서 모든 섬이 연결될 수 있도록 하면서 환경 부담금을 최소화하는 해결책을 찾아야 한다. 문제의 요구 사항은 그래프의 최소 신장 트리를 구하는 것과 유사하다고 볼 수 있다.
풀이 과정
섬들 간의 모든 가능한 연결을 고려하여 각 연결 비용을 계산한 후, 이를 기반으로 최소 신장 트리(MST)를 구성해야 한다. 각 연결 비용은 주어진 섬들의 좌표를 이용하여 유클리드 거리의 제곱으로 계산되며, 이 값에 환경 부담 세율 E를 곱한다. 이 문제를 해결하기 위해 프림 알고리즘 또는 크루스칼 알고리즘을 사용할 수 있다. 계산된 최소 신장 트리의 총 비용을 반올림하여 출력해야 한다.
코드
import java.io.*;
import java.util.*;
public class Main {
// Edge 클래스는 각 섬 간의 연결을 나타내며, 비교가 가능하도록 Comparable 인터페이스를 구현한다.
static class Edge implements Comparable<Edge> {
int start, end; // 시작 섬과 끝 섬의 인덱스
double cost; // 연결 비용
Edge(int start, int end, double cost) {
this.start = start;
this.end = end;
this.cost = cost;
}
// 비용을 기준으로 오름차순 정렬하기 위한 메소드
@Override
public int compareTo(Edge o) {
return Double.compare(this.cost, o.cost);
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine()); // 테스트 케이스의 수를 입력받음
for (int tc = 1; tc <= T; tc++) { // 각 테스트 케이스에 대해 반복
int N = Integer.parseInt(br.readLine()); // 섬의 개수
int[] x = new int[N]; // 섬들의 X 좌표
int[] y = new int[N]; // 섬들의 Y 좌표
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
x[i] = Integer.parseInt(st.nextToken());
}
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
y[i] = Integer.parseInt(st.nextToken());
}
double E = Double.parseDouble(br.readLine()); // 환경 부담 세율
// 모든 가능한 연결을 우선순위 큐에 추가
PriorityQueue<Edge> pq = new PriorityQueue<>();
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
double dist = Math.pow(x[i] - x[j], 2) + Math.pow(y[i] - y[j], 2);
pq.add(new Edge(i, j, E * dist)); // 비용 계산 후 큐에 추가
}
}
// 크루스칼 알고리즘으로 최소 신장 트리 구성
int[] parent = new int[N]; // 각 섬의 부모를 저장하는 배열
for (int i = 0; i < N; i++) {
parent[i] = i; // 초기화
}
double result = 0;
int count = 0;
while (!pq.isEmpty()) {
Edge edge = pq.poll(); // 가장 비용이 낮은 연결을 꺼냄
if (union(edge.start, edge.end, parent)) { // 사이클이 없으면 해당 간선을 추가
result += edge.cost;
if (++count == N - 1) break; // 모든 섬이 연결되면 종료
}
}
// 결과 출력
bw.write("#" + tc + " " + Math.round(result) + "\n");
}
bw.flush();
bw.close();
}
// 유니온 파인드의 'find' 함수
static int find(int a, int[] parent) {
if (a == parent[a]) return a;
return parent[a] = find(parent[a], parent);
}
// 유니온 파인드의 'union' 함수
static boolean union(int a, int b, int[] parent) {
int rootA = find(a, parent);
int rootB = find(b, parent);
if (rootA != rootB) {
parent[rootB] = rootA; // 두 섬을 연결
return true;
}
return false;
}
}
시간 복잡도 분석
시간 복잡도는 크루스칼 알고리즘을 사용했기 때문에 𝑂(𝐸log𝐸)이다. 여기서 𝐸는 섬 간의 가능한 모든 연결 수이며, 섬의 개수 𝑁에 따라 𝑂(𝑁^2)의 연결이 가능하다.
느낀점
이 문제를 통해 최소 신장 트리 알고리즘의 중요성을 다시 한 번 확인할 수 있었다. 또한, 실수 연산과 관련된 문제에서는 자료형 선택에 주의해야 함을 알게 되었다.
반응형
'SW Expert Academy > D4' 카테고리의 다른 글
[SWEA/Java] 5672. 올해의 조련사 (1) | 2024.04.21 |
---|---|
[SWEA/Java] 6109. 추억의 2048게임 (0) | 2024.04.21 |
[SWEA/Java] 7465. 창용 마을 무리의 개수 (1) | 2024.04.19 |
[SWEA/Java] 3289. 서로소 집합 (1) | 2024.04.19 |
[SWEA/Java] 7208. 지도 칠하기 (1) | 2024.04.19 |
Comments