[ 백준 17136 ] 색종이 붙이기 ( java )
<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다.
<그림 1>
색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는 1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야 한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고, 겹쳐도 안 된다. 또, 칸의 경계와 일치하게 붙여야 한다. 0이 적힌 칸에는 색종이가 있으면 안 된다.
종이가 주어졌을 때, 1이 적힌 모든 칸을 붙이는데 필요한 색종이의 최소 개수를 구해보자.
입력
총 10개의 줄에 종이의 각 칸에 적힌 수가 주어진다.
출력
모든 1을 덮는데 필요한 색종이의 최소 개수를 출력한다. 1을 모두 덮는 것이 불가능한 경우에는 -1을 출력한다.
출처: 백준 코딩 테스트 연습, https://www.acmicpc.net/problem/17136
핵심
1 dfs
dfs는 지도를 탐색하다 1이 나오면 크기 1~5 종이로 덮고, 다음 dfs를 부른다.
만약 덮지 못하면 종료.
모든 1을 덮었다면 사용한 종이 비교 후 종료
이 때,
1 의미: 덮어야 위치
0 의미: 덮지 말아야 하며, 이미 색종이가 붙여있을 수 있다.
( 바보같이 색종이 5개 세는 곳에서 <, <= 차이로 틀렸었는데 테스트케이스는 통과 됐었다. )
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
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());
}
}
int[] use = new int[5];
dfs(0, use);
if(min == Integer.MAX_VALUE)
System.out.println(-1);
else
System.out.println(min);
}
static int[][] map = new int[10][10];
static int min = Integer.MAX_VALUE;
static void dfs(int y, int[] use) {
if(allCover()) {
int cnt = 0;
for(int i = 0 ; i < 5 ; i++) {
cnt += use[i];
}
if(min > cnt)
min = cnt;
return;
}
for(int i = y ; i < 10 ; i++) {
for(int j = 0 ; j < 10 ; j++) {
if(map[i][j] == 1) {
for(int paper = 4 ; paper >=0 ; paper-- ) {
if(use[paper] < 5 && canCover(i, j, paper)) {
use[paper]++;
cover(i, j, paper);
dfs(i, use);
uncover(i, j, paper);
use[paper]--;
}
}
return;
}
}
}
}
// 1인 부분만 덮어야 한다. 0이 있다면 덮지 못 함.
static boolean canCover(int y, int x, int delta) {
int ny, nx;
for(int dy = 0 ; dy <= delta ; dy++) {
for(int dx = 0 ; dx <= delta; dx++) {
ny = y + dy;
nx = x + dx;
if(!(ny>=0 && ny < 10 && nx >= 0 && nx < 10))
return false;
if(map[ny][nx] == 0)
return false;
}
}
return true;
}
static void cover(int y, int x, int delta) {
int ny, nx;
for(int dy = 0 ; dy <= delta ; dy++) {
for(int dx = 0 ; dx <= delta; dx++) {
ny = y + dy;
nx = x + dx;
map[ny][nx] = 0;
}
}
}
static void uncover(int y, int x, int delta) {
int ny, nx;
for(int dy = 0 ; dy <= delta ; dy++) {
for(int dx = 0 ; dx <= delta; dx++) {
ny = y + dy;
nx = x + dx;
map[ny][nx] = 1;
}
}
}
static boolean allCover() {
for(int i = 0 ; i < 10 ; i++) {
for(int j = 0 ; j < 10 ; j++) {
if(map[i][j] == 1)
return false;
}
}
return true;
}
}
|
cs |
'CS > 알고리즘 풀이' 카테고리의 다른 글
[ 백준 14502 ] 연구소 ( 자바 ) (0) | 2020.02.17 |
---|---|
[ 백준 17406 ] 배열 돌리기 4 ( 자바 ) (0) | 2020.02.17 |
[ 백준 17135 ] 캐슬 디펜스 ( 자바 ) (0) | 2020.02.16 |
[ 백준 17070 ] 파이프 옮기기 1 ( 자바 ) (0) | 2020.02.12 |
[ 백준 13460 ] 구슬 탈출 2 ( 자바 ) (0) | 2020.02.11 |