https://www.acmicpc.net/problem/17136
17136번: 색종이 붙이기
<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다. <그림 1> 색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는 1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야 한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고, 겹쳐
www.acmicpc.net
17136 색종이 붙이기
알고리즘 : 비트마스크 DFS
삼성 A형 기출문제입니다. 문제 풀이 방법은 1767 프로세서 연결하기와 매우 유사합니다.
https://mumomu.tistory.com/13?category=863413
[SWEA / 삼성A형기출] 1767 프로세서 연결하기 풀이
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV4suNtaXFEDFAUf SW Expert Academy SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요! swexpertacademy..
mumomu.tistory.com
이 문제의 특징을 보면 맵이 한 줄이 10으로 고정되어 있고 0과 1로 이루어진 것을 알 수 있습니다.
이는 하나의 int형으로 한 줄을 관리할 수 있다는 것이고 위의 문제와 유사합니다.
이를 이용하면 시간을 많이 단축할 수 있습니다.
그렇게 가능한 칸마다 남아있는 5*5~1*1의 색종이를 붙이고 다음 칸으로 진행하는 것을 반복하면
최저 횟수가 나옵니다.
예전 초등학교 정보올림피아드 지역예선에서 비슷한 문제를 봤던 것 같습니다.
< CODE >
#include <iostream>
#include <vector>
using namespace std;
#define MAX 10
vector<pair<int, int>> v;
int result = 987654321;
// 색종이를 붙일 수 있는지 확인
bool bitCheck(int bit, int x, int width)
{
int chk = (((1 << width) - 1) << x);
return chk == (chk & bit);
}
// 해당영역의 1을 0으로 바꿔야하므로 해당부분을 1로 만든 뒤 반전하여 &연산
void bitChange(int & bit, int x, int width)
{
bit &= ~(((1 << width) - 1) << x);
}
void dfs(int cnt, int bit[MAX], int remain[6], int amount)
{
if (amount == v.size())
{
int total = 0;
for (int i = 1; i < 6; i++)
total += (5 - remain[i]);
if (total < result)
result = total;
return;
}
else if (cnt == v.size())
return;
int y = v[cnt].first;
int x = v[cnt].second;
if (!bitCheck(bit[y], x, 1))
dfs(cnt + 1, bit, remain, amount);
int base[MAX];
// 비트 복구를 위한 베이스
for (int i = 0; i < MAX; i++)
base[i] = bit[i];
for (int i = 5; i > 0; i--)
{
if (remain[i] == 0)
continue;
bool chk = true;
for (int j = 0; j < i; j++)
chk &= bitCheck(bit[y + j], x, i);
if (chk)
{
for (int j = 0; j < i; j++)
bitChange(bit[y + j], x, i);
remain[i] -= 1;
dfs(cnt + 1, bit, remain, amount + i * i);
remain[i] += 1;
for (int j = 0; j < i; j++)
bit[y + j] = base[y + j];
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int bit[MAX] = { 0, };
int remain[6] = { 0,5,5,5,5,5 };
int amount = 0;
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < MAX; j++)
{
int num;
cin >> num;
if (num == 1)
{
bit[i] |= (1 << j);
v.push_back({ i,j });
}
}
}
dfs(0, bit, remain, 0);
if (result == 987654321)
cout << "-1\n";
else
cout << result << '\n';
return 0;
}
56ms로 통과하였습니다.
#삼성A형기출 #백준 17136 #17136 색종이붙이기풀이
'알고리즘' 카테고리의 다른 글
[BOJ / 라인스위핑] 9318 위성사진 (0) | 2020.07.21 |
---|---|
[알고스팟 / 비트마스크 DP] GRADUATION 졸업학기 (0) | 2020.07.08 |
[BOJ / 삼성A형기출] 16234 인구 이동 (0) | 2020.02.24 |
[BOJ / 삼성A형기출] 13460 구술 탈출 2 (0) | 2020.02.18 |
[SWEA / 삼성A형기출] 1767 프로세서 연결하기 (0) | 2020.02.16 |