• 문제 링크
17136번: 색종이 붙이기
<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다. <그림 1> 색종이를 크
www.acmicpc.net
• 풀이 과정
10 * 10 크기의 2차원 배열에 색종이를 붙일 수 있는 면적에 대한 정보를 입력받고
크기가 1 * 1 ~ 5 * 5 인 각각의 색종이의 사용 가능한 개수를 기록할 paper 배열을 생성한다.
전체 면적을 재귀 함수를 활용하여 최상단 행에서 우측으로 모두 탐색 후, (x == 10)
아래 행으로 내려가는 방식(recur(y + 1, 0, cnt)) 으로 탐색한다.
만약 현재 좌표가 색종이를 붙일 수 없는 좌표라면 다음 x 축으로 재귀 호출,
색종이를 붙일 수 있다면 현재 좌표는 색종이의 왼쪽 상단의 꼭지점이 된다.
해당 꼭지점을 기준으로 큰 크기 색종이부터 탐색하며, 해당 색종이가 사용 가능한 여분이 있는지 (papar[i] > 0)
또한 그 크기만큼 면적에 붙일 수 있는지 (canAttach(y, x, i)) 확인하여,
만약 붙일 수 있는 조건에 만족한다면 잔여 개수를 하나 소진하고, (paper[i]--)
convert 함수를 통해 색종이를 붙인 후
사용한 색종이의 개수를 1 증가시키는 재귀 호출 뒤, 원 상태로 복귀한다.
모든 면적의 탐색을 완료하였다면, (y == 10) 현재까지 누적된 색종이의 사용 개수와 최소값을 비교하여
최종적으로 갱신된 최소값을 정답으로써 출력한다.
• 풀이 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
static int[][] map;
static int[] paper = {0, 5, 5, 5, 5, 5};
static int min = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
map = new int[10][10];
for (int i = 0; i < 10; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 10; j++)
map[i][j] = Integer.parseInt(st.nextToken());
}
recur(0, 0, 0);
bw.write(min == Integer.MAX_VALUE ? "-1" : String.valueOf(min));
bw.flush();
}
private static void recur(int y, int x, int cnt) {
if (y == 10) {
min = Math.min(min, cnt);
return;
}
if (x == 10) {
recur(y + 1, 0, cnt);
return;
}
if (map[y][x] == 1) {
for (int i = 5; i > 0; i--) {
if (paper[i] > 0 && canAttach(y, x, i)) {
paper[i]--;
convert(y, x, i, 0);
recur(y, x + 1, cnt + 1);
convert(y, x, i, 1);
paper[i]++;
}
}
} else
recur(y, x + 1, cnt);
}
private static boolean canAttach(int y, int x, int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (y + i > 9 || x + j > 9 || map[y + i][x + j] == 0)
return false;
}
}
return true;
}
private static void convert(int y, int x, int size, int state) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
map[y + i][x + j] = state;
}
}
}
'Problem Solving > Baekjoon' 카테고리의 다른 글
[백준] 1987 알파벳 - Backtracking / Java (0) | 2022.09.23 |
---|---|
[백준] 16987 계란으로 계란치기 - Backtracking / Java (0) | 2022.09.22 |
[백준] 16945 매직 스퀘어로 변경하기 - Backtracking / Java (0) | 2022.09.20 |
[백준] 15684 사다리 조작 - Backtracking / Java (0) | 2022.09.19 |
[백준] 14889 스타트와 링크 - Backtracking / Java (0) | 2022.09.18 |
댓글