Algorithm/백준

[BOJ] - 17136. 색종이 붙이기

benguin 2019. 4. 9. 01:52

[URL]

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

 

[문제 풀이]

 

* 재귀 DFS

 

1. map[][] == 1인부분 vector v에 info형태(x, y)로 저장

2. v의 갯수만큼 완전 탐색 검사 실시

3.  check[cx][cy] 현재 위치 이미 업데이트 된 곳인가?

4. isPossible() n==5부터 현 위치와 n사이즈를 가능 여부 체크

5. checkUp(cx, cy, n, 1) 현재 위치 부터 nxn만큼 1로 업데이트

 

 

[소스 코드]

 

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <stdio.h>
#include <vector>
 
using namespace std;
 
// type
struct info {
    int x;
    int y;
};
 
// variable
vector <info> v;
int paper[5= { 55555 };
int map[10][10];
bool check[10][10= { 0, };
int cand[987654];
int candCnt = 0;
 
// func
void init();
bool isPossible(int x, int y, int nSize);
void checkUp(int x, int y, int nSize, int value);
void go(int pos);
 
int main()
{
    init();
 
    go(0);
 
    if (candCnt != 0)
    {
        int Min = 987654;
        for (int i = 0; i < candCnt; i++)
        {
            if (cand[i] <= Min)
            {
                Min = cand[i];
            }
        }
        printf("%d\n", Min);
    }
    else
        printf("-1\n");
 
    return 0;
}
 
void init()
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            scanf("%d"&map[i][j]);
 
            if (map[i][j] == 1)
            {
                info temp;
                temp.x = i;
                temp.y = j;
 
                v.push_back(temp);
            }
        }
    }
}
 
bool isPossible(int x, int y, int nSize)
{
    if (paper[nSize - 1< 1)
        return false;
 
    for (int i = x; i < x + nSize; i++)
    {
        for (int j = y; j < y + nSize; j++)
        {
            if (i < 0 || j < 0 || i >= 10 || j >= 10)
                return false;
 
            if (map[i][j] != 1)
                return false;
 
            if (check[i][j])
                return false;
        }
    }
 
    return true;
}
 
void checkUp(int x, int y, int nSize, int value)
{
    for (int i = x; i < x + nSize; i++)
    {
        for (int j = y; j < y + nSize; j++)
        {
            check[i][j] = value;
        }
    }
}
 
void go(int pos)        // map[][] == 1인 곳 완전탐색
{
    if (pos == v.size())
    {
        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            sum += paper[i];
        }
        cand[candCnt++= 25 - sum;
 
        return;
    }
 
    int cx = v[pos].x;
    int cy = v[pos].y;
 
    if (check[cx][cy])        // 현 위치가 이미 업데이트 된 곳인가?
        go(pos + 1);
 
    for (int n = 5; n > 0; n--)
    {
        if (isPossible(cx, cy, n))        // 현 위치와 n사이즈 검사
        {
            paper[n - 1]--;        // n사이즈 색종이 갯수 -1
            checkUp(cx, cy, n, 1);        // 현 위치 업데이트
 
            go(pos + 1);
 
            checkUp(cx, cy, n, 0);        // 현 위치 업데이트 취소
            paper[n - 1]++;        // n사이즈 색종이 갯수 +1
        }
    }
}
cs

'Algorithm > 백준' 카테고리의 다른 글

[BOJ] - 14888. 연산자 끼워넣기  (0) 2019.04.09
[BOJ] - 14889. 스타트와 링크  (0) 2019.04.09
[BOJ] - 16235. 나무 재테크  (0) 2019.04.08
[BOJ] - 17135. 캐슬 디펜스  (0) 2019.04.08
[BOJ] - 15683. 감시  (0) 2019.04.08