✏️ 문제 분석
https://www.acmicpc.net/problem/16937
HxW크기 격자에 R1xC1, R2xC2, ..., RnxCn 크기 스티커 중 2개를 붙일 때 (스티커 90도 회전 가능)
두 스티커가 붙여진 넓이의 최댓값은?
✏️ 구현 아이디어
격자에 두 스티커를 붙일 때 이렇게 네 가지 경우가 나온다.

같이 붙일 수 있다면 max값을 갱신하여 가장 넓은 값을 출력한다.
✏️ 시간 복잡도
스티커 100개 중 2개를 고르는 경우의 수는 100_P_2 = 100*99/2 = 4,950가지
스티커 한 개를 붙일 수 있는지 확인하는 로직은 O(2)이므로 시간 안에 연산 가능하다.
✏️ 알고리즘
모든 경우를 다 탐색하는 브루트포스를 사용한다.
✏️ 오답 노트
언급했던 네 가지 방법만 확인하면 안 된다.
반례 :

이 경우 90도 회전하면 스티커를 붙일 수 있다.

그래서 네 경우가 아니라 90도 회전한 경우를 추가해 8가지 경우를 고려해야 한다.
✏️ 코드 설계
- 입력값 받기
- sticker[]에서 두 개의 스티커를 꺼내서 isPossible로 확인
- isPossible : s1, s2를 격자에 붙일 수 있는지 확인하는 함수
- 8가지 경우를 구현하여 HxW 격자 밖으로 스티커가 나가지 않는지 확인
- 스티커를 붙일 수 있으면 true 반환
- 가독성을 위해서 if문 나열함
- max값을 갱신하여 가장 큰 값을 리턴
✏️ 정답 코드
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static Sticker[] sticker;
static int H, W, N;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
H = Integer.parseInt(st.nextToken());
W = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
sticker = new Sticker[N];
for(int i=0; i<N; i++){
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
sticker[i] = new Sticker(r, c);
}
int ans = 0;
//스티커 2개 선택
for(int i=0; i<N; i++){
for(int j=i+1; j<N; j++){
//붙일 수 있다면
if(isPossible(sticker[i], sticker[j])){
//둘의 넓이 합 구해서
int totalArea = (sticker[i].c * sticker[i].r) + (sticker[j].c * sticker[j].r);
//최댓값 갱신
ans = Math.max(ans, totalArea);
}
}
}
System.out.println(ans);
}
//스티커 붙일 수 있는지 확인
static boolean isPossible(Sticker s1, Sticker s2){
int r1 = s1.r, c1 = s1.c;
int r2 = s2.r, c2 = s2.c;
boolean ret = false;
int[][] tmp = {{H, W},{W, H}}; //격자 자체를 90도로 회전시킴
for(int i=0; i<2; i++){
int a = tmp[i][0];
int b = tmp[i][1];
//스티커 붙이는 4가지 조합 확인
if(r1+r2<=a && Math.max(c1, c2)<=b) ret = true;
if(r1+c2<=a && Math.max(c1, r2)<=b) ret = true;
if(c1+r2<=a && Math.max(r1, c2)<=b) ret = true;
if(c1+c2<=a && Math.max(r1, r2)<=b) ret = true;
}
return ret;
}
}
class Sticker{
int r, c;
Sticker(int r, int c){
this.r = r;
this.c = c;
}
}
✏️ Note
- 처음에 구현 아이디어를 떠올리기가 어려웠다.
- 그리고 나 스스로 처음부터 모든 경우를 빠짐 없이 고려하기가 어렵다. 꼭 테케를 한 번 돌려서 우연히 반례가 발견되거나 질문 게시판에서 반례를 뒤져야 된다.
- 그냥 아직 구현 문제가 어려운 것 같다. 더 익숙해져야겠다.
'코테' 카테고리의 다른 글
| [백준/Java] 2529번 : 부등호 (0) | 2025.02.06 |
|---|---|
| [백준/Java] 1182번 : 부분 수열의 합 (1) | 2025.02.04 |
| [백준/Java] 1283번 : 단축키 지정 (2) | 2025.01.26 |
| [백준/Java] 11060번 : 점프 점프 (2) | 2025.01.25 |
| [백준/Java] 25644번 : 경비원 (0) | 2025.01.24 |