문제 설명
폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.
- 정사각형은 서로 겹치면 안 된다.
- 도형은 모두 연결되어 있어야 한다.
- 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.
아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.
테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.
테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.
문제 풀이
이 문제는 어떻게 효율적으로 풀가 고민하게 되면 늪에 빠지게 되는 문제라고 생각됩니다.
각 블록의 형태도 다르고 대칭성이 없는 블록, 회전해도 똑같은 블록이 존재하기에 각 블록마다 케이스를 잡고 브루트포스를 통해 구현해주면 쉽게 해결되는 문제입니다.
각 블록의 케이스는 어떻게 구하든 N, M만큼 반복문을 돌게되면 모든 대칭, 회전한 케이스까지 검토할 수 있으므로 자신이 편한대로 케이스를 잡아주시면 됩니다.
풀이 코드
import java.io.*;
import java.util.*;
public class Main {
private static int N, M;
private static int[][] map;
private static int[][][] blockCase = new int[][][]{
{{0, 0}, {0, 1}, {1, 0}, {1, 1}}, // 네모 블럭
{{0, 0}, {0, 1}, {0, 2}, {0, 3}}, // l블록 가로배치
{{0, 0}, {1, 0}, {2, 0}, {3, 0}}, // l블록 세로 배치
{{0, 0}, {0, 1}, {0, 2}, {1, 1}}, // ㅜ블록 배치
{{0, 0}, {0, 1}, {0, 2}, {-1, 1}}, // ㅗ블록 배치
{{0, 0}, {1, 0}, {2, 0}, {1, 1}}, // ㅏ블록 배치
{{0, 0}, {1, 0}, {2, 0}, {1, -1}}, // ㅓ블록 배치
{{0, 0}, {1, 0}, {1, 1}, {2, 1}}, // 4번째 블록 정배치
{{0, 0}, {1, 0}, {1, -1}, {2, -1}}, // 4번째 블록 정배치 대칭
{{0, 0}, {0, -1}, {1, -1}, {1, -2}}, // 4번째 블록 우측 1회전
{{0, 0}, {0, 1}, {1, 1}, {1, 2}}, // 4번째 블록 우측 1회전 대칭
{{0, 0}, {1, 0}, {2, 0}, {2, 1}}, // L블록 배치
{{0, 0}, {1, 0}, {2, 0}, {2, -1}}, // L블록 대칭 배치
{{0, 0}, {1, 0}, {0, 1}, {0, 2}}, // ㄱ블록(가로 긴 버전) 대칭 배치
{{0, 0}, {0, 1}, {0, 2}, {1, 2}}, // ㄱ블록(가로 긴 버전) 배치
{{0, 0}, {0, 1}, {1, 1}, {2, 1}}, // ㄱ블룩(세로 긴 버전) 배치
{{0, 0}, {0, 1}, {1, 0}, {2, 0}}, // ㄱ블록(세로 긴 버전) 대칭 배치
{{0, 0}, {1, 0}, {1, 1}, {1, 2}}, // ㄴ블록 배치
{{1, 0}, {1, 1}, {1, 2}, {0, 2}} // ㄴ블록 대칭 배치
};
public static void main(String[] args) throws IOException {
input();
solve();
}
private static void solve() {
int ans = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
for (int k = 0; k < blockCase.length; k++) {
int sum = 0;
boolean isBlock = true;
for (int t = 0; t < 4; t++) {
int bx = i + blockCase[k][t][0]; // 체크하고자 하는 블록의 x
int by = j + blockCase[k][t][1]; // 체크하고자 하는 블록의 y
if (bx < 0 || by < 0 || bx >= N || by >= M) {
isBlock = false;
break;
}
sum += map[bx][by];
}
if (!isBlock) continue;
ans = Math.max(ans, sum);
}
}
}
System.out.println(ans);
}
private static void input() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
}
}
<출처>
https://www.acmicpc.net/problem/14500
반응형
'백준' 카테고리의 다른 글
[BOJ][Java] 백준 1406번: 에디터 (1) | 2022.11.16 |
---|---|
[BOJ][Java] 백준 1202번: 보석 도둑 (0) | 2022.07.28 |
[BOJ][Java] 백준 4796번: 캠핑 (0) | 2022.07.28 |
[BOJ][Java] 백준 2011번: 암호코드 (0) | 2022.07.03 |
[BOJ][Java] 백준 16637번: 괄호 추가하기 (0) | 2022.06.01 |
댓글