https://www.acmicpc.net/problem/4386
4386번: 별자리 만들기
도현이는 우주의 신이다. 이제 도현이는 아무렇게나 널브러져 있는 n개의 별들을 이어서 별자리를 하나 만들 것이다. 별자리의 조건은 다음과 같다. 별자리를 이루는 선은 서로 다른 두 별을 일
www.acmicpc.net
난이도 : 골드 3
태그 : 그래프 이론, 최소 스패닝 트리
1. 설명
모든 별을 선으로 이어 별자리를 만드는 문제입니다.
별자리를 잇는다는 건, 두 별을 직선으로 이은 것이며, 모든 별자리는 직/간접적으로 서로 이어져 있어야 합니다.
별을 이을 때 거리만큼의 비용이 들 때, 모든 별을 직/간접적으로 이으면서 그 비용이 최소가 되는 경우를 찾아야 합니다.
"모든 별(노드)를 선으로 직/간접적으로 이으면서, 그 비용이 최소가 된다"라는 점에서, 최소 스패닝 트리 문제임을 알 수 있습니다.
최소 스패닝 트리에 대해 잘 모르겠다면 아래 포스팅을 참고해주세요.
https://uknowblog.tistory.com/294
[알고리즘] 최소 스패닝 트리 (MST, Minimum Spanning Tree)
최소 스패닝 트리 / 최소 신장 트리 (MST, Minimun Spanning Tree) 스패닝 트리 / 신장 트리는 모든 정점(Vertex, Node)을 간선(Edge)로 사이클이 생기지 않게 연결한 그래프입니다. 최소 스패닝 트리 / 최소 신
uknowblog.tistory.com
다행이도 별들은 이차원 평면 위에 놓여져 있습니다.
즉, 두 별을 직선으로 이었을 때 거리는 피타고라스로 쉽게 구할 수 있습니다.
다른 최소 스패닝 트리에서는 노드와 연결된 간선도 주어지지만,
이 문제에서는 노드와 그 좌표만 주어질 뿐, 간선의 정보는 주어지지 않습니다.
따라서 저는 그냥 n개의 별 중 2개의 별을 이은 모든 간선을 만들어준 뒤,
크루스칼 알고리즘과 유니온 파인드를 사용해 풀이하였습니다.
2. 소스코드
<kotlin />
import java.util.PriorityQueue
import kotlin.math.pow
import kotlin.math.sqrt
data class Node(val from: Int, val to: Int, val weight: Double) : Comparable<Node> {
override fun compareTo(other: Node): Int {
return if(this.weight > other.weight) 1 else -1
}
}
data class Star(var x: Double, var y: Double)
var total = 0.0
lateinit var parent: Array<Int>
fun main() {
val n = readLine()!!.toInt()
parent = Array(n + 1) { it }
val stars = Array<Star>(n) { Star(0.0, 0.0) }
val pq = PriorityQueue<Node>()
for (i in 0 until n) {
val line = readLine()!!.split(" ")
stars[i].x = line[0].toDouble()
stars[i].y = line[1].toDouble()
for (j in 0 until i) {
val weight = sqrt((stars[i].x - stars[j].x).pow(2) + (stars[i].y - stars[j].y).pow(2))
pq.add(Node(i, j, weight))
}
}
while(pq.isNotEmpty()) {
val node = pq.poll()
if (find(node.from) != find(node.to)) {
total += node.weight
union(node.from, node.to)
}
}
println(total)
}
fun find(x: Int): Int {
return if (parent[x] == x) x
else {
parent[x] = find(parent[x])
parent[x]
}
}
fun union(x: Int, y: Int) {
val nx = find(x)
val ny = find(y)
if (nx != ny) {
if(x < y) {
parent[ny] = nx
} else {
parent[nx] = ny
}
}
}
3. 후기
별들을 이어 별자리를 만든다는 낭만적인 문제였습니다.
'코딩테스트 > Kotlin' 카테고리의 다른 글
[백준 24481번] [Kotlin] 알고리즘 수업 - 깊이 우선 탐색 3 (0) | 2023.09.23 |
---|---|
[백준 24480번] [Kotlin] 알고리즘 수업 - 깊이 우선 탐색 2 (0) | 2023.09.23 |
[백준 1261번] [Kotlin] 알고스팟 (0) | 2023.09.19 |
[백준 21609번] [Kotlin] 상어중학교 (0) | 2023.09.14 |
[백준 16920번] [Kotlin] 확장 게임 (0) | 2023.09.11 |