// 2250년, 인류는 지구 뿐 아니라 여러 행성을 다니며 살고 있다.
// 이 행성 간을 빨리 오가기 위해 새롭게 터널을 구축하려 한다.
// 행성은 (x, y, z) 좌표로 주어진다.
// 행성1: (x1, y1, z1), 행성2: (x2, y2, z2)
// 이 때 행성간 터널 연결 비용은 min(|x1-x2|, |y1-y2|, |z1-z2|) 로 계산한다.
// n 개의 행성 사이를 n-1 개의 터널로 연결하는데 드는 최소 비용을 구하는 프로그램을 작성하세요.
// 입출력 예시
// 입력:
// data = {{11, -15, -15}, {14, -5, -15}, {-1, -1, -5}, {10, -4, -1}, {19, -4, 19}}
// 출력: 4
import java.util.Arrays;
import java.util.PriorityQueue;
public class Practice1 {
static int[] parents;
/**
* 정렬을 해야지 가중치 마이너스 상황에서 최소값을 뽑는다..?!!
* 엥 그럼 정렬 안하고.. abs()로 구하면 안됨? -> 된다 ! 하지만 이중 포문 비효율적!
* -> 애초에 최소 가중치 간선만 간선으로 생성한다면 효율적이게 된다
* -> 정렬하여 앞뒤 노드의 가중치만 계산한다면 최소 가중치들만 뽑게 되는 것임 !!!
*/
public static int solution(int[][] data) {
parents = new int[data.length];
for (int i = 0; i < parents.length; i++) {
parents[i] = i;
}
PriorityQueue<Edge> pq = new PriorityQueue<>((x, y) -> x.weight - y.weight);
/**
* 이렇게 해도 정답은 나옴 -> 이중 for문 때문에 비효율적
* -> 정렬하여 최소 간선만 만들기로 효율화 가능
*/
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][0] - data[j][0])));
// }
// }
// }
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][1] - data[j][1])));
// }
// }
// }
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][2] - data[j][2])));
// }
// }
// }
Arrays.sort(data, (x, y) -> x[0] - y[0]); // 정렬하여 최소 가중치 간선만 생성하여 효율적
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][0] - data[i + 1][0])));
}
Arrays.sort(data, (x, y) -> x[1] - y[1]);
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][1] - data[i + 1][1])));
}
Arrays.sort(data, (x, y) -> x[2] - y[2]);
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][2] - data[i + 1][2])));
}
int weightSum = 0;
while (!pq.isEmpty()) {
Edge polled = pq.poll();
if (find(polled.from) != find(polled.to)) {
union(polled.from, polled.to);
weightSum += polled.weight;
}
}
return weightSum;
}
public static int find(int target) {
if (target == parents[target]) {
return target;
}
return parents[target] = find(parents[target]);
}
public static void union(int a, int b) {
int resultA = find(a);
int resultB = find(b);
parents[resultA] = resultB;
}
public static void main(String[] args) {
// Test code
int[][] data = {{11, -15, -15}, {14, -5, -15}, {-1, -1, -5}, {10, -4, -1}, {19, -4, 19}};
System.out.println(solution(data));
}
public static class Edge {
int from;
int to;
int weight;
public Edge(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
}
}
// 2250년, 인류는 지구 뿐 아니라 여러 행성을 다니며 살고 있다.
// 이 행성 간을 빨리 오가기 위해 새롭게 터널을 구축하려 한다.
// 행성은 (x, y, z) 좌표로 주어진다.
// 행성1: (x1, y1, z1), 행성2: (x2, y2, z2)
// 이 때 행성간 터널 연결 비용은 min(|x1-x2|, |y1-y2|, |z1-z2|) 로 계산한다.
// n 개의 행성 사이를 n-1 개의 터널로 연결하는데 드는 최소 비용을 구하는 프로그램을 작성하세요.
// 입출력 예시
// 입력:
// data = {{11, -15, -15}, {14, -5, -15}, {-1, -1, -5}, {10, -4, -1}, {19, -4, 19}}
// 출력: 4
import java.util.Arrays;
import java.util.PriorityQueue;
public class Practice1 {
static int[] parents;
/**
* 정렬을 해야지 가중치 마이너스 상황에서 최소값을 뽑는다..?!!
* 엥 그럼 정렬 안하고.. abs()로 구하면 안됨? -> 된다 ! 하지만 이중 포문 비효율적!
* -> 애초에 최소 가중치 간선만 간선으로 생성한다면 효율적이게 된다
* -> 정렬하여 앞뒤 노드의 가중치만 계산한다면 최소 가중치들만 뽑게 되는 것임 !!!
*/
public static int solution(int[][] data) {
parents = new int[data.length];
for (int i = 0; i < parents.length; i++) {
parents[i] = i;
}
PriorityQueue<Edge> pq = new PriorityQueue<>((x, y) -> x.weight - y.weight);
/**
* 이렇게 해도 정답은 나옴 -> 이중 for문 때문에 비효율적
* -> 정렬하여 최소 간선만 만들기로 효율화 가능
*/
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][0] - data[j][0])));
// }
// }
// }
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][1] - data[j][1])));
// }
// }
// }
// for (int i = 0; i < data.length; i++) {
// for (int j = 0; j < data.length; j++) {
// if (i != j) {
// pq.add(new Edge(i, j, Math.abs(data[i][2] - data[j][2])));
// }
// }
// }
Arrays.sort(data, (x, y) -> x[0] - y[0]); // 정렬하여 최소 가중치 간선만 생성하여 효율적
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][0] - data[i + 1][0])));
}
Arrays.sort(data, (x, y) -> x[1] - y[1]);
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][1] - data[i + 1][1])));
}
Arrays.sort(data, (x, y) -> x[2] - y[2]);
for (int i = 0; i < data.length - 1; i++) {
pq.add(new Edge(i, i + 1, Math.abs(data[i][2] - data[i + 1][2])));
}
int weightSum = 0;
while (!pq.isEmpty()) {
Edge polled = pq.poll();
if (find(polled.from) != find(polled.to)) {
union(polled.from, polled.to);
weightSum += polled.weight;
}
}
return weightSum;
}
public static int find(int target) {
if (target == parents[target]) {
return target;
}
return parents[target] = find(parents[target]);
}
public static void union(int a, int b) {
int resultA = find(a);
int resultB = find(b);
parents[resultA] = resultB;
}
public static void main(String[] args) {
// Test code
int[][] data = {{11, -15, -15}, {14, -5, -15}, {-1, -1, -5}, {10, -4, -1}, {19, -4, 19}};
System.out.println(solution(data));
}
public static class Edge {
int from;
int to;
int weight;
public Edge(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
}
}