Posts 2887 planet tunnel
Post
Cancel

2887 planet tunnel

2887 planet tunnel

알고리즘(정렬, MST)

1
2
3
4
5
6
1. 모든 행성들의 x좌표, y좌표, z좌표를 꺼내 따로 저장하고, 오름차순으로 정렬
2. 정렬한 것에서 인접한 것끼리 비용을 계산, (인접한 점 두개 + 비용)을 구조체로 n-1개의 원소를 가지는 배열 3개를 선언하고 집어넣음
3. 그 구조체배열 3개는 비용을 기준으로 오름차순으로 정렬
4. 구조체 배열 3개를 가리키는 3개의 인덱스 변수 xi, yi, zi를 선언
5. xi, yi, zi 중 최소 비용을 unionFind 알고리즘으로 사이클이 형성되는지 확인하면서 집어넣음. 넣으면 edge 1증가, 넣어도 안넣어도 xi, yi, zi는 최소일시 1 증가시킨다
6. edge가 n-1개가 되면 정지 -> 총 value 출력

푼과정

1
2
3
4
5
6
7
8
9
1. MST로 풀어야하는 문제인건 바로 암. 근데 간선이 주어지지 않음 -> 간선을 직접 만들어야함
2. 모든 행성간의 비용을 구하는건 너무 오래걸리고, 메모리 소모가 심함
	-> 가장 가까운 것이 될 만한 것들끼리만 비교하여 간선을 만들자
3. 모든 행성을 정렬하여 인접한 것끼리 할까?
	-> 어떤 기준으로 정렬할 것인지 문제고, 또 정렬하더라도 인접하지만 거리는 제일 멀 수 있음 -> 비용계산공식이 좌표별로 독립적이기에
4. 그럼 좌표별로 모든 점들을 정렬하여 인접한 것끼리 비용을 계산하고, 또 그 비용을 정렬하면 되겠구나
	-> 그럼 비용, 두 인접한 좌표를 가지고 있는 구조체를 선언하는게 좋겠구나
5. 이렇게 간선을 얻고, 하나씩 집어넣는데 총 edge는 N-1개니까 넣을 때마다 edge를 1개씩 증가시켜 n-1이 되면 정지시키면 되겠구나
6. 통과

코드

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#define MAX_PLANET 100000

using namespace std;

typedef struct Planet {
	int x;
	int y;
	int z;
} Planet;
typedef struct Distance {
	int first;
	int second;
	int distance;
	bool operator < (Distance d) {
		return distance < d.distance;
	}
} Distance;

Planet planet[MAX_PLANET];
Distance xyz[3][MAX_PLANET];
int numOfPlanet, checkPlanet[MAX_PLANET], tempXYZ[MAX_PLANET];
vector<vector<int>> set;

int abs(int a) {
	return a < 0 ? (-1) * a : a;
}
long long getMinValue();
bool putSet(int a, int b);
bool compX(int a, int b) {
	return planet[a].x < planet[b].x;
}
bool compY(int a, int b) {
	return planet[a].y < planet[b].y;
}
bool compZ(int a, int b) {
	return planet[a].z < planet[b].z;
}
void initAndSortXYZ();

int main() {
	cin >> numOfPlanet;
	for (int i = 0; i < numOfPlanet; i++)
		cin >> planet[i].x >> planet[i].y >> planet[i].z;
	for (int i = 0; i < MAX_PLANET; i++)
		checkPlanet[i] = -1;

	cout << getMinValue();
}

long long getMinValue() {
	long long value = 0;
	int Xi = 0, Yi = 0, Zi = 0, edge = 0;
	initAndSortXYZ();
	while (edge < numOfPlanet - 1) {
		int xd = xyz[0][Xi].distance, yd = xyz[1][Yi].distance, zd = xyz[2][Zi].distance;
		if (xd <= yd && xd <= zd) {
			if (putSet(xyz[0][Xi].first, xyz[0][Xi].second)) {
				value += xd;
				edge++;
			}
			Xi++;
		}
		else if (yd <= xd && yd <= zd) {
			if (putSet(xyz[1][Yi].first, xyz[1][Yi].second)) {
				value += yd;
				edge++;
			}
			Yi++;
		}
		else {
			if (putSet(xyz[2][Zi].first, xyz[2][Zi].second)) {
				value += zd;
				edge++;
			}
			Zi++;
		}
	}

	return value;
}

void initAndSortXYZ() {
	cout << endl;
	for (int k = 0; k < 3; k++) {
		for (int i = 0; i < numOfPlanet; i++)
			tempXYZ[i] = i;

		if(k == 0) sort(tempXYZ, tempXYZ + numOfPlanet, compX);
		else if(k==1)  sort(tempXYZ, tempXYZ + numOfPlanet, compY);
		else if(k==2)  sort(tempXYZ, tempXYZ + numOfPlanet, compZ);

		for (int i = 0; i < numOfPlanet - 1; i++) {
			xyz[k][i].first = tempXYZ[i];
			xyz[k][i].second = tempXYZ[i + 1];
			if (k == 0)
				xyz[k][i].distance = abs(planet[tempXYZ[i]].x - planet[tempXYZ[i + 1]].x);
			else if (k == 1)
				xyz[k][i].distance = abs(planet[tempXYZ[i]].y - planet[tempXYZ[i + 1]].y);
			else if (k == 2)
				xyz[k][i].distance = abs(planet[tempXYZ[i]].z - planet[tempXYZ[i + 1]].z);
		}
		for (int i = 0; i < numOfPlanet - 1; i++)
			cout << "( " << xyz[k][i].first << ", " << xyz[k][i].second << ", " << xyz[k][i].distance << ") ";
		sort(xyz[k], xyz[k] + numOfPlanet -1);
		for (int i = 0; i < numOfPlanet - 1; i++)
			cout << "( " << xyz[k][i].first << ", " << xyz[k][i].second << ", " << xyz[k][i].distance << ") ";
		cout << endl;
	}

	cout << endl;

}

bool putSet(int a, int b) {
	if (checkPlanet[a] == -1 && checkPlanet[b] == -1) {
		vector<int> temp;
		temp.push_back(a);
		temp.push_back(b);
		set.push_back(temp);
		checkPlanet[a] = set.size() - 1;
		checkPlanet[b] = set.size() - 1;
	}
	else if (checkPlanet[a] == -1) {
		checkPlanet[a] = checkPlanet[b];
		set[checkPlanet[b]].push_back(a);
	}
	else if (checkPlanet[b] == -1) {
		checkPlanet[b] = checkPlanet[a];
		set[checkPlanet[a]].push_back(b);
	}
	else if (checkPlanet[a] < checkPlanet[b]) {
		int temp = checkPlanet[b];
		for (int i = 0; i < set[temp].size(); i++) {
			checkPlanet[set[temp][i]] = checkPlanet[a];
			set[checkPlanet[a]].push_back(set[temp][i]);
		}
		set[temp].clear();
	}
	else if (checkPlanet[a] > checkPlanet[b]) {
		int temp = checkPlanet[a];
		for (int i = 0; i < set[temp].size(); i++) {
			checkPlanet[set[temp][i]] = checkPlanet[b];
			set[checkPlanet[b]].push_back(set[temp][i]);
		}
		set[temp].clear();
	}
	else
		return false;
	return true;
}
This post is licensed under CC BY 4.0 by the author.

2568 전기줄

2931 가스관

Comments powered by Disqus.