Study hard
(c++)백준 17136번: 색종이 붙이기 본문
17136번: 색종이 붙이기
<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다. <그림 1> 색종이를 크��
www.acmicpc.net
[풀이]
dfs를 이용하여 백트래킹을 하였다.
1. 종이에서 1 찾기: 1 없으면 지금까지 붙여왔던 종이 개수와 최솟값 비교하여 갱신
2. 1이 있는 칸에 1*1, 2*2, 3*3, 4*4, 5*5 종이를 붙일 수 있는지 확인(종이 붙이는 범위 안에 0이 있으면 안 됨)
3. 종이를 붙이고 붙인 종이 개수에 +1하여 재귀
4. 붙인 종이 떼기
#include <iostream>
#include <algorithm>
using namespace std;
const int Max = 10;
int Min = 987654321;
int Map[Max][Max];
int paper[] = { 0,0,0,0,0, };//1,2,3,4,5쓰인 개수
bool can_attach(int x, int y, int s) {
for (int i = 0; i <= s; i++) {
for (int j = 0; j <= s; j++) {
if (Map[x + i][y + j] == 0)
return false;
}
}
return true;
}
void update_Map(int x, int y, int s, int attached) {
for (int i = 0; i <= s; i++) {
for (int j = 0; j <= s; j++) {
Map[x + i][y + j] = attached;
}
}
}
void dfs(int x, int y, int paper_cnt) {
//1찾기
while (Map[x][y] == 0) {
if (++y >= 10) {
if (++x >= 10) {
Min = min(Min, paper_cnt);
return;
}
y = 0;
}
}
//현재까지의 최솟값 보다 크면 가지치기
if (Min <= paper_cnt)
return;
//모든 종이에 대해
for (int i = 4; i >= 0; i--) {
//범위 벗어나거나 해당 종이 5장 다 썼을 경우
if (x + i >= Max || y + i >= Max || paper[i] == 5)
continue;
//붙일 수 있으면(해당 영역이 모두 1이면)
if (can_attach(x, y, i)) {
paper[i]++;
update_Map(x, y, i, 0);
dfs(x, y, paper_cnt + 1);
paper[i]--;
update_Map(x, y, i, 1);
}
}
}
void solution() {
int total_one = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
cin >> Map[i][j];
if (Map[i][j] == 1)
total_one++;
}
}
if (total_one == 0) {
cout << 0 << '\n';
return;
}
else if(total_one == Max * Max) {
cout << 4 << '\n';
return;
}
dfs(0, 0, 0);
if (Min == 987654321)
cout << -1 << '\n';
else
cout << Min << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
solution();
return 0;
}
'백준 > bfs, dfs' 카테고리의 다른 글
(c++)백준 17406번: 배열 돌리기 4 (0) | 2020.10.12 |
---|---|
(c++)백준 17281번: ⚾ (0) | 2020.10.12 |
(c++)백준 17145번: 캐슬 디펜스 (0) | 2020.10.12 |
(c++)백준 17070번: 파이프 옮기기 1 (0) | 2020.10.11 |
(c++)백준 16637번: 괄호 추가하기 (0) | 2020.10.11 |