https://www.acmicpc.net/problem/10775
G개의 게이트가 있으며 각각은 1에서 G까지의 번호를 가지고 있음P개의 비행기가 순서대로 도착할 예정i번째 비행기를 1번부터 Gi번째 게이트 중 하나에 영구적으로 도킹처음 문제를 접근했을 때에는 도착하는 비행기의 번호에서 시작하여, 도킹할 수 있는 번호가 나올 때까지 탐색하였습니다.
public static boolean parking(int num) {
while (num-- > 0) {
if (!parked[num]) {
parked[num] = true;
answer++;
return true;
}
}
return false;
}
위와 같은 방식으로 찾으면 시간 초과가 발생하게 됩니다.
이 문제는 시간복잡도가 최대 O(G * P)가 나옵니다.
여기서 G와 P의 최댓값인 10의 5승이 나오게 되면 1초 안에 끝날 수 없게 되죠.
이를 해결하기 위해 위 메서드를 수정할 필요가 있습니다.
그래서 생각해낸 것이 Union-Find였습니다.
비행기가 도킹할 수 있는 위치는 비행기 번호 이하의 자연수입니다.
부모 배열을 자기 자신으로 선언 후, 도킹을 하게 되면 부모 - 1의 값으로 부모를 바꿔버리는 방법이죠
private static void make() {
parked = new boolean[G+1];
p = new int[G+1];
for (int i = 1; i <= G; i++) {
p[i] = i;
}
}
private static int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]); // 경로 압축
}
private static void union(int a, int b) {
p[find(a)] = find(b);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
G = Integer.parseInt(br.readLine());
P = Integer.parseInt(br.readLine());
make();
for (int i = 0; i < P; i++) {
int g = Integer.parseInt(br.readLine()); // 도킹할 비행기 번호
int x = find(g); // 비행기가 도킹할 게이트 번호
if (x == 0) break; // 없다면 종료
parked[x] = true; // 도킹
answer++; // 도킹 횟수 + 1
union(x, x-1); // 바로 앞 번호로 도킹할 번호 변경
}
System.out.println(answer);
}
parent가 0이라면 주차할 공간이 없다는 뜻이기 때문에, 문제 조건에 의하여 종료하면 됩니다.import java.io.*;
public class Main {
static int G, P;
static int[] p;
static boolean[] parked;
static int answer = 0;
private static void make() {
parked = new boolean[G+1];
p = new int[G+1];
for (int i = 1; i <= G; i++) {
p[i] = i;
}
}
private static int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]);
}
private static void union(int a, int b) {
p[find(a)] = find(b);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
G = Integer.parseInt(br.readLine());
P = Integer.parseInt(br.readLine());
make();
for (int i = 0; i < P; i++) {
int g = Integer.parseInt(br.readLine());
int x = find(g);
if (x == 0) break;
parked[x] = true;
answer++;
union(x, x-1);
}
System.out.println(answer);
}
}