<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다.
색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는 1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야 한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고, 겹쳐도 안 된다. 또, 칸의 경계와 일치하게 붙여야 한다. 0이 적힌 칸에는 색종이가 있으면 안 된다.
종이가 주어졌을 때, 1이 적힌 모든 칸을 붙이는데 필요한 색종이의 최소 개수를 구해보자.
총 10개의 줄에 종이의 각 칸에 적힌 수가 주어진다.
모든 1을 덮는데 필요한 색종이의 최소 개수를 출력한다. 1을 모두 덮는 것이 불가능한 경우에는 -1을 출력한다.
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
4
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
5
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
-1
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
7
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
4
0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 1 1 1 1 1 1 1 1 1
0 1 1 1 0 1 1 1 1 1
0 1 1 1 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
6
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 0 1 1 1 1
1 1 1 1 1 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 1 1 0 0 0
0 1 1 1 0 1 1 0 0 0
0 1 1 1 0 0 0 0 0 1
5
문제 유형 : 브루트포스, 백트랙킹
import java.io.*;
import java.util.*;
/* 붙일 수 있는 색종이의 최솟값을 찾는 문제
* 각 색종이는 5장씩
*/
public class Main_bj_17136_색종이붙이기 {
static int ans;
static int[][] paper;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
paper = new int[10][10];
StringTokenizer st;
for (int i = 0; i < 10; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < 10; j++) {
paper[i][j] = Integer.parseInt(st.nextToken());
}
}
ans = 100; // 최댓값으로 초기화
int[] remain = new int[] {0, 5, 5, 5, 5, 5}; // 남은 색종이의 갯수
bp(0, 0, remain, 0); // 0, 0 부터 붙이기 시작
if(ans==100) ans=-1;
System.out.println(ans);
br.close();
}
static void bp(int x, int y, int[] remain, int cnt) {
if(x==9 && y==10) {
ans = Math.min(ans, cnt);
return;
}
if(cnt > ans) return;
if(y>=10) {
bp(x+1, 0, remain, cnt); // 다음 줄로 넘어감
return;
}
if(paper[x][y]==1) { // 색종이를 붙인다
for(int k=5; k>=1; k--) { // 5사이즈의 종이부터 붙여본다
if(isAttach(x, y, k) && remain[k]>0) {
attach(x, y, k);
remain[k]--; // 남은 색종이 갯수 차감
bp(x, y+1, remain, cnt+1); // 다음 칸으로
detach(x, y, k);
remain[k]++; // 원상복구
}
}
}
else { // 다음 칸으로
bp(x, y+1, remain, cnt);
}
}
// size 만큼의 색종이를 붙일 수 있는지 확인하는 과정
static boolean isAttach(int x, int y, int size) {
for(int i=x; i<x+size; i++) {
for(int j=y; j<y+size; j++) {
if(i>=10 || j>=10 || paper[i][j]!=1) return false;
}
}
return true;
}
// 색종이를 붙이는 과정
static void attach(int x, int y, int size) {
for(int i=x; i<x+size; i++) {
for(int j=y; j<y+size; j++) {
paper[i][j] = 2;
}
}
}
// 색종이를 뗴는 과정
static void detach(int x, int y, int size) {
for(int i=x; i<x+size; i++) {
for(int j=y; j<y+size; j++) {
paper[i][j] = 1;
}
}
}
}