문제 풀이/백준
[백준] 2655번. 가장높은탑쌓기(JAVA)
27200
2025. 6. 13. 11:43
문제
https://www.acmicpc.net/problem/2655
풀이(40분)
import java.io.*;
import java.util.*;
public class Main {
static int N;
static int[][] blocks; // [i][0]: 밑면 넓이, [1]: 높이, [2]: 무게
static Info[] dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
blocks = new int[N + 1][3];
for (int i = 1; i <= N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < 3; j++) {
blocks[i][j] = Integer.parseInt(st.nextToken());
}
}
dp = new Info[N + 1];
Info result = new Info(0, "");
// 모든 블록을 위에 둘 수 있는 경우를 탐색
for (int i = 1; i <= N; i++) {
Info candidate = buildTower(i);
if (candidate.height > result.height) {
result = candidate;
}
}
// 결과 문자열 처리 (쌓은 블록 번호를 역순 출력)
String[] usedBlocks = result.order.trim().split(" ");
StringBuilder sb = new StringBuilder();
sb.append(usedBlocks.length).append("\n");
for (int i = usedBlocks.length - 1; i >= 0; i--) {
sb.append(usedBlocks[i]).append("\n");
}
System.out.print(sb);
}
// 특정 블록을 가장 위에 둘 때 최대 높이와 블록 순서를 반환
static Info buildTower(int top) {
if (dp[top] != null) return dp[top];
int maxHeight = blocks[top][1];
String towerOrder = "";
for (int below = 1; below <= N; below++) {
if (blocks[below][0] < blocks[top][0] && blocks[below][2] < blocks[top][2]) {
Info belowInfo = buildTower(below);
int candidateHeight = blocks[top][1] + belowInfo.height;
if (candidateHeight > maxHeight) {
maxHeight = candidateHeight;
towerOrder = belowInfo.order;
}
}
}
dp[top] = new Info(maxHeight, top + " " + towerOrder);
return dp[top];
}
// 블록을 쌓은 결과를 저장하는 클래스: 높이와 블록 순서
static class Info {
int height;
String order;
Info(int height, String order) {
this.height = height;
this.order = order;
}
}
}
문제 풀이 전략
중요 포인트는 아래에서 위로 쌓아가는 게 아닌 위에서 아래로 쌓는 방식으로 생각을 하는 것이다.
또한, dp를 활용해 이전에 탐색했던 블록에 대한 정보가 있다면 이를 재활용하게 하여 최적화한다.