https://www.acmicpc.net/problem/17136
&Title
17136번 - 색종이 붙이기
&Question
<그림 1>과 같이 정사각형 모양을 한 다섯 종류의
색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로
총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고
있다.<그림 1>색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는
1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는
1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야
한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고,
겹쳐도 안 된다. 또, 칸의 경계와 일치하게 붙여야 한다.
0이 적힌 칸에는 색종이가 있으면 안 된다.종이가 주어졌을 때,
1이 적힌 모든 칸을 붙이는데 필요한 색종이의 최소 개수를
구해보자.
&Input
총 10개의 줄에 종이의 각 칸에 적힌 수가
주어진다.
&Output
모든 1을 덮는데 필요한 색종이의 최소 개수를 출력한다.
1을 모두 덮는 것이 불가능한 경우에는 -1을 출력한다.
&Example
-input
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
-output
0
-input
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
-output
4
-input
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
-output
5
-input
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
-output
-1
-input
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
-output
7
-input
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
-output
4
-input
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
-output
6
-input
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
-output
5
#include <iostream>
#include <algorithm>
using namespace std;
int map[10][10];
int paper[6] = { 0, 5, 5, 5, 5, 5 };
int res = 1e9;
void dfs(int y, int x, int cnt) {
// 기저 조건 : 결과보다 작으면 갱신할 가치가 없음
if (cnt > res)return;
// 81까지 끝까지 돌았으니 최솟값 갱신
if (y == 10) {
res = min(res, cnt);
return;
}
// x좌표 넘어가면 다음줄로 넘겨줌
if (x == 10) {
dfs(y + 1, 0, cnt);
return;
}
// 값 0이면 넘어감
if (map[y][x] == 0) {
dfs(y, x + 1, cnt);
}
// 크기 5~1까지 가능한 경우 재귀 돌려줌(큰거부터 해야 최솟값 갱신에 더 효율적
for (int sz = 5; sz >= 1; --sz) {
if (y + sz > 10 || x + sz > 10 || paper[sz] == 0)continue;
bool flag = true;
// 색종이를 붙일 수 있는지 확인
for (int i = y; i < y + sz; ++i) {
for (int j = x; j < x + sz; ++j)
if (map[i][j] == 0) {
flag = false;
break;
}
if (!flag)break;
}
if (!flag)continue;
// 색종이를 붙여줌
for (int i = y; i < y + sz; ++i)
for (int j = x; j < x + sz; ++j)
map[i][j] = 0;
paper[sz]--;
dfs(y, x + sz, cnt + 1);
// 색종이를 뗌
for (int i = y; i < y + sz; ++i)
for (int j = x; j < x + sz; ++j)
map[i][j] = 1;
paper[sz]++;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)
cin >> map[i][j];
dfs(0, 0, 0);
if (res == 1e9)res = -1;
cout << res << endl;
return 0;
}
댓글남기기