Algorithm
[Algo] 백준 1516 게임 개발 JAVA
조핑구
2024. 5. 8. 13:56
문제 바로가기 : https://www.acmicpc.net/problem/1516
메모리 : 22260KB
시간 : 288ms
언어 : Java 11
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(br.readLine());
StringTokenizer st;
Queue<Integer> q = new LinkedList<>();
List<List<Integer>> list = new ArrayList<>();
int[] time = new int[N + 1];
int[] ans = new int[N + 1];
int[] cnt = new int[N + 1];
for (int i = 0; i <= N; i++) {
list.add(new ArrayList<>());
}
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
time[i] = Integer.parseInt(st.nextToken());
int num = Integer.parseInt(st.nextToken());
if (num == -1) {
ans[i] = time[i];
q.add(i);
} else {
cnt[i]++;
list.get(num).add(i);
while (true) {
num = Integer.parseInt(st.nextToken());
if (num == -1)
break;
cnt[i]++;
list.get(num).add(i);
}
}
}
while (!q.isEmpty()) {
int now = q.poll();
for (int next : list.get(now)) {
cnt[next]--;
ans[next] = Math.max(ans[now] + time[next], ans[next]);
if (cnt[next] == 0)
q.add(next);
}
}
for (int i = 1; i <= N; i++) {
sb.append(ans[i]).append("\n");
}
System.out.print(sb);
}
}
순서를 지켜가며 해결해야하는 문제이기때문에 위상정렬을 이용해 풀 수 있다. 어떤 건물 A를 짓기 전 지어야 하는 건물들을 이어보면 트리를 만들 수 있다. 문제에 케이스는 모두 건물을 지을 수 있는 경우로 주어진다고 했으니 맨 처음 조건없이 지을 수 있는 건물들을 시작으로 하나씩 지어나가면 된다. 건물을 지어가며 Queue에 넣어주면 되는데, cnt배열을 사용하지 않았을 때 시간초과가 발생한다. Queue에는 건물이 한 번씩만 들어가야하는데 이를 위해 조건이 만족된 건물만 넣어주기 위해 cnt배열을 사용한다. 앞선 건물이 완공되면 즉 cnt가 0이면 공사를 할 수 있는 순서가 되어 Queue에 입장하는 것이다.
++ "위상"이라는 말이 궁금해서 사전을 찾아보니 관계 속에서 가지는 위치라는 말이었다. 위상수학이라는 것도 있었다. 뭔가 항상 애매한 개념이었는데 뜻을 알고나니 오래 기억할것같은 기분😎