1516번: 게임 개발
첫째 줄에 건물의 종류 수 N(1 ≤ N ≤ 500)이 주어진다. 다음 N개의 줄에는 각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어진다. 건물의 번호는 1부
www.acmicpc.net
1. 문제 설명
어떤 건물을 짓기 전에 그 건물을 짓기 전에 지어야 하는 건물들을 지은 후에 지을 수 있다. 여러 개의 건물을 동시에 지을 수 있고, 건물을 짓는 명령을 내리기까지 시간이 걸리지 않는다고 하고,
각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어질 때, 각 건물이 완성되기까지 걸리는 최소 시간을 출력하는 문제이다.
2. 풀이
백준 2056번 작업과 유사한 문제이다. 위상 정렬에 대해서 알지 못한다면 먼저 문제를 풀어보는걸 추천한다.
[JAVA]백준 2056번: 작업
www.acmicpc.net/problem/2056 2056번: 작업 수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있..
kwoncorin.tistory.com
작업 문제와 다른 점은 작업 문제에서는 현재 작업을 수행하기 전에 완료되어야 하는 작업들의 번호가 현재 작업의 번호보다 작았다. 현재 작업의 번호가 K라고 하면 이전에 수행되어야 하는 작업들은 1 이상 K-1이하의 번호를 가졌다. 하지만 이번 문제에서는 그러한 조건이 없기에 다이나믹 프로그래밍으로만 푸는 것보다는 위상정렬로 푸는 것이 더 효율적이다.
dp[X]=Math.max(dp[X],time[X]+dp[이전건물])
현재 건물 X를 짓는데 걸리는 최소시간은 현재 건물 X를 짓기 위해 이전에 지어야 하는 건물들을 짓기까지의 시간과 현재 건물 X를 짓는데만 걸리는 시간의 최댓값이다.
이러한 식과 위상 정렬을 이용하면 쉽게 풀 수 있다.
3. 코드
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
int building_num;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
building_num = Integer.parseInt(br.readLine());
int[] time = new int[building_num + 1];
int[] dp = new int[building_num + 1];
int[] in = new int[building_num + 1];
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
for (int x = 0; x <= building_num; x++) {
list.add(new ArrayList<>());
}
for (int x = 1; x <= building_num; x++) {
StringTokenizer input = new StringTokenizer(br.readLine());
int size = input.countTokens() - 1;
time[x] = Integer.parseInt(input.nextToken());
for (int y = 1; y < size; y++) {
int pre = Integer.parseInt(input.nextToken());
list.get(pre).add(x);
in[x]++;
}
}
for (int x = 1; x <= building_num; x++) {
if (in[x] == 0) {
dp[x] = time[x];
queue.add(x);
}
}
while (!queue.isEmpty()) {
int now = queue.poll();
int arr_size = list.get(now).size();
for (int y = 0; y < arr_size; y++) {
int base = list.get(now).get(y);
in[base]--;
dp[base] = Math.max(dp[base], time[base] + dp[now]);
if (in[base] == 0) {
queue.add(base);
}
}
}
for (int x = 1; x <= building_num; x++) {
bw.write(String.valueOf(dp[x]) + "\n");
}
bw.flush();
bw.close();
br.close();
}
}
'알고리즘' 카테고리의 다른 글
[JAVA]백준 3020번: 개똥벌레 (0) | 2021.03.30 |
---|---|
[JAVA]백준 14728번: 벼락치기 (0) | 2021.03.18 |
[JAVA]백준 17070번: 파이프 옮기기 1 (0) | 2021.03.12 |
[JAVA]백준 7579번: 앱 (0) | 2021.03.08 |
[JAVA]백준 2073번: 수도배관공사 (0) | 2021.03.06 |