Link https://www.acmicpc.net/problem/17136
소스결과 1988 KB / 36 ms
언어 C++ 17
출처 Baekjoon
분류 브루트 포스
설명
10 x 10 의 판에 1 이 적힌 부분을 덮기 위해 필요한 색종이의 수를 구하여라.
삽질에 삽질에 삽질을 했던 문제. 타임아웃 문제를 해결해야 했던 문제도, 그리디로 처리해 오답이 나온 경우도 있었다.
타임아웃의 경우는 한 위치에서 5x5 색종이가 놓는게 가능하다 할 때 이 위치는 4,3,2,1 이 가능하기때문에 모든 경우에 다 대입하는 방법이었는데 시간도 오래 걸릴 뿐 더러, 굳이 할 필요가 없는 문제였다.
그리디로 처리한 경우는 예제중 한 경우도 통과 못했었다.
정답은 타임아웃 경우를 조금 수정한 방법이었는데. 색종이를 놓을 수 있는 가장 처음 위치(0,0)에 가장 가까운 위치를 기준으로 놓을 수 있는 모든 경우를 대입하여 처리 하는 방법이었다.
알고리즘
1. 색종이를 놓을 첫 위치를 탐색한다.
2. 첫 위치에 대해서 5x5가 가능한 경우 1x1까지 탐색한다.
3. 위치가 결정된 뒤, 색종이를 놓은게 처리가 되면, 다음 위치를 탐색하고 이동한다.
3-1. 색종이는 각각 5장이 최대이므로, 남은 색종이가 없으면 놓지 않는다.
4. 다음 위치도 2번과 같은 알고리즘으로 처리한다.
5. 결과값을 출력한다.
소스코드
#include <iostream>
using namespace std;
const short BOARD_MAX = 10;
struct Point {
short x;
short y;
Point() { };
Point(short x, short y) : x(x), y(y) {}
};
bool board[BOARD_MAX][BOARD_MAX];
int res = -1;
bool locationAble(bool board[BOARD_MAX][BOARD_MAX], Point p, int size)
{
bool res = false;
if (p.x + size <= BOARD_MAX && p.y + size <= BOARD_MAX)
{
res = true;
for (int i = p.x; i < p.x + size; i++)
for (int j = p.y; j < p.y + size; j++)
if (!board[i][j])
return false;
}
return res;
}
bool isClear(bool board[BOARD_MAX][BOARD_MAX])
{
for (int i = 0; i < BOARD_MAX; i++)
for (int j = 0; j < BOARD_MAX; j++)
if (board[i][j])
return false;
return true;
}
Point nextPoint(bool board[BOARD_MAX][BOARD_MAX])
{
Point res(BOARD_MAX, BOARD_MAX);
for (int i = 0; i < BOARD_MAX; i++) {
for (int j = 0; j < BOARD_MAX; j++)
{
if (board[i][j]) {
res.x = i;
res.y = j;
break;
}
}
if (res.x != BOARD_MAX && res.y != BOARD_MAX)
break;
}
return res;
}
void solution(bool board[BOARD_MAX][BOARD_MAX], int paper[5], Point p, int cnt)
{
if (p.x == BOARD_MAX && p.y == BOARD_MAX)
{
if (res == -1)
res = cnt;
else
if (res > cnt)
res = cnt;
}
else
{
for (int s = 5; s > 0; s--)
{
if (paper[s - 1] > 0)
{
if (locationAble(board, p, s))
{
for (int px = p.x; px < p.x + s; px++)
for (int py = p.y; py < p.y + s; py++)
board[px][py] = false;
Point next = nextPoint(board);
paper[s - 1]--;
solution(board, paper, next, cnt + 1);
paper[s - 1]++;
for (int px = p.x; px < p.x + s; px++)
for (int py = p.y; py < p.y + s; py++)
board[px][py] = true;
}
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
for (int i = 0; i < BOARD_MAX; i++)
for (int j = 0; j < BOARD_MAX; j++)
cin >> board[i][j];
int paper[] = { 5, 5, 5, 5, 5 };
solution(board, paper, nextPoint(board), 0);
cout << res;
return 0;
}
'Algorithm > Brute Force' 카테고리의 다른 글
Baekjoon 2231 분해합 (0) | 2019.08.21 |
---|---|
Baekjoon 17135 캐슬 디펜스 (0) | 2019.06.02 |
Baekjoon 14500 테트로미노 (0) | 2019.06.02 |
Baekjoon 16675 두 개의 손 (0) | 2019.03.31 |
Baekjoon 12100 2048 (Easy) (0) | 2019.03.08 |