설명
밑면이 정사각형인 벽돌들을 아래에서 위로 쌓아 올려 가장 높게 탑을 만드는 문제입니다.
단, 벽돌을 쌓을 때 아래 조건들을 반드시 지켜야 합니다.
쌓을 수 있는 조건
- 벽돌은 회전 불가 (가로세로 바꿔서 쓸 수 없음)
- 밑면 넓이가 큰 벽돌만 작은 벽돌 위에 올 수 있음
- 무게가 더 가벼운 벽돌 위에 무거운 벽돌을 올릴 수 없음
- 밑면 넓이와 무게가 같은 벽돌은 없다 (→ 중복을 신경 쓸 필요 없음)
입력
- 첫 줄: 벽돌의 수 N (1 ≤ N ≤ 100)
- 다음 줄부터: 각 벽돌의 (밑면 넓이, 높이, 무게) 정보가 주어짐
- 모든 값은 10,000 이하의 자연수
출력
- 만들 수 있는 가장 높은 탑의 총 높이
🔍 예시
예시 입력
5
25 3 4
4 4 6
9 2 3
16 2 5
1 5 2
예시 출력
10
해결 방법
- 넓이 기준 내림차순 정렬
- 밑면 넓이 기준으로 정렬하면 이후에는 넓이 조건은 자동으로 만족하게 됩니다.
- 따라서 DP에서는 무게만 비교하면 됩니다.
- DP 배열 의미 (dy[i])
- dy[i]는 i번째 벽돌을 꼭대기에 두었을 때 만들 수 있는 최대 높이를 저장합니다.
- 이전 문제 LIS에서 dp[i] = max(dp[j]) + 1처럼, 여기선 dy[i] = max(dy[j]) + arr[i].h로 표현됩니다.
- 탑을 쌓는 조건
- arr[j].w > arr[i].w이면 무게가 더 무거운 벽돌이 더 아래에 놓인 것이므로 유효합니다.
- 넓이 조건은 정렬로 보장되므로 무게 조건만 검사하면 됩니다.
코드 구현
import java.util.*;
class Brick implements Comparable<Brick> {
public int s, h, w;
public Brick(int s, int h, int w) {
this.s = s;
this.h = h;
this.w = w;
}
@Override
public int compareTo(Brick ob) {
return ob.s - this.s; // 내림차순 정렬 (넓이가 큰 벽돌 먼저)
}
}
public class Main {
static int[] dy;
static int n;
public int solution(ArrayList<Brick> arr) {
int answer;
Collections.sort(arr); // 넓이 기준 내림차순 정렬
dy[0] = arr.get(0).h;
answer = dy[0];
for(int i=1; i<n; i++) {
int max = 0;
for(int j=i-1; j>=0; j--) {
if(arr.get(j).w > arr.get(i).w && dy[j] > max) {
max = dy[j];
}
}
dy[i] = max + arr.get(i).h;
answer = Math.max(answer, dy[i]);
}
return answer;
}
public static void main(String[] args) {
Main T = new Main();
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
dy = new int[n];
ArrayList<Brick> arr = new ArrayList<>();
for(int i=0; i<n; i++) {
int s = sc.nextInt();
int h = sc.nextInt();
int w = sc.nextInt();
arr.add(new Brick(s, h, w));
}
System.out.print(T.solution(arr));
sc.close();
}
}
코드 설명
- Brick 클래스: 벽돌의 넓이(s), 높이(h), 무게(w)를 필드로 가짐
- compareTo: 넓이 기준으로 내림차순 정렬 → 밑면 넓이가 큰 순서대로 정렬됨
- dy[i]: i번째 벽돌을 가장 위에 올렸을 때 만들 수 있는 최대 탑의 높이
- dy[i] = max(dy[j]) + arr[i].h → i보다 넓이/무게가 모두 큰 j 벽돌들 중에서 가장 높은 곳에 이어 쌓기
시간 복잡도 분석
- O(N²) : 이중 for문으로 i와 j를 비교하면서 조건에 맞는 벽돌을 쌓는 방식
출처: 인프런 자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비
https://www.inflearn.com/course/자바-알고리즘-문제풀이-코테대비/dashboard
자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비 강의 | 김태원 - 인프런
김태원 | , 자바(Java) 알고리즘 문제풀이 채점사이트를 통해 기초부터 준비해보세요! 💪 [사진] 이 강의는 [사진] 자바(Java)로 코딩테스트 준비를 하고 계신 분께 추천드려요! 문제는 기초~ 중급
www.inflearn.com
'코딩테스트 > 자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비' 카테고리의 다른 글
| 섹션 10 Dynamic Programming - 6. 최대점수 구하기(냅색 알고리즘) (1) | 2025.06.14 |
|---|---|
| 섹션 10 Dynamic Programming - 5. 동전교환(냅색 알고리즘) (1) | 2025.06.14 |
| 섹션 10 Dynamic Programming - 3. 최대 부분 증가수열(LIS) (0) | 2025.06.14 |
| 섹션 10 Dynamic Programming - 2. 돌다리 건너기 (1) | 2025.06.13 |
| 섹션 10 Dynamic Programming - 1. 계단오르기 (0) | 2025.06.13 |