반응형

문제 출처 :


https://www.acmicpc.net/problem/17136



알고리즘 분석 :


문제 해결에 필요한 사항

1. 구현

2. BFS


완전 탐색을 통해 그냥 색종이를 계속 붙여가며 최소 몇개로 모두 0으로 만들 수 있는지 찾는 문제이다.


자세한 풀이 과정은 아래 주석을 통해 달아두었다.






소스 코드 : 


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 <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
 
using namespace std;
 
typedef pair<intint> pii;
 
// 큐정보
// 맵, y,x,cnt, 색종이 남은 개수
struct INFO {
    int map[12][12];
    int y, x;
    int cnt;
    int colorPaper[6];
};
 
int arr[12][12];
pii point; // 첫좌표 받는 임시 변수
 
// 맵 복사 함수
void copyMap(int dest[][12], int src[][12]) {
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            dest[i][j] = src[i][j];
}
 
// 해당하는 시작 좌표에서 n크기의 사각형이 모두 1인지 확인
bool checkArea(int n, int y, int x, int map[][12]) {
    for (int i = y; i < y + n; i++)
        for (int j = x; j < x + n; j++)
            if (!(<= i && i < 10 && 0<= j && j < 10 && map[i][j]))
                return false;
    return true;
}
 
// 해당하는 시작 좌표에서 n크기의 사각형 지우기
void fillArea(int n, int y, int x, int map[][12]) {
    for (int i = y; i < y + n; i++)
        for (int j = x; j < x + n; j++)
            map[i][j] = 0;
}
 
// 모두 0으로 되어있는지 확인
bool isOnlyZero(int map[][12]) {
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            if (map[i][j])
                return false;
    return true;
}
int main() {
    point = { -1-};
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++) {
            scanf("%d"&arr[i][j]);
            // 처음 1로 시작하는 좌표 받는다.
            if (arr[i][j] && point.first == -1)
                point = { i,j }; 
        }
 
    // 답이 없을때 -1이기에 ans = -1로 시작
    int ans = -1;
 
    INFO info;
    copyMap(info.map, arr);
    info.cnt = 0;
    info.y = point.first;
    info.x = point.second;
    // 색종이는 모두 5개있다.
    for (int i = 0; i < 6; i++)
        info.colorPaper[i] = 5;
 
    queue<INFO> q;
 
    q.push(info);
 
    while (!q.empty()) {
        INFO here = q.front();
        q.pop();
        int map[12][12];
        copyMap(map, here.map);
        int y = here.y;
        int x = here.x;
        int cnt = here.cnt;
        int colorPaper[6];
        for (int i = 0; i < 6; i++)
            colorPaper[i] = here.colorPaper[i];
        
        // ans가 갱신됐으며 cnt가 갱신된 ans보다 크면 볼필요 없다.
        if (ans != -&& cnt > ans)
            continue;
 
        // 모두 다 지웠으면 ans 갱신
        if (isOnlyZero(map)) {
            if (ans == -1)
                ans = cnt;
            ans = min(ans, cnt);
        }
 
        // 크기 1~5짜리 색종이 하나씩 다 붙여보는 과정(완전탐색)
        for (int i = 1; i <= 5; i++) {
            // 색종이가 남아있고 해당 위치에 해당 크기 색종이 붙일 수 있으면
            if (colorPaper[i] - >= && checkArea(i, y, x, map)) {
                INFO tmp;
                copyMap(tmp.map, map);
                fillArea(i, y, x, tmp.map);
                tmp.cnt = cnt + 1;
                for (int j = 0; j < 6; j++)
                    tmp.colorPaper[j] = colorPaper[j];
                tmp.colorPaper[i] --;
 
                bool chk = false;
                for (int a = 0; a < 10; a++) {
                    for (int b = 0; b < 10; b++) {
                        // 처음 1로 시작하는 좌표 담아주고 break
                        if (tmp.map[a][b]) {
                            tmp.y = a;
                            tmp.x = b;
                            chk = true;
                            break;
                        }
                    }
                    if (chk)
                        break;
                }
 
                q.push(tmp);
            }
        }
    }
 
    printf("%d", ans);
    return 0;
}
cs

반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[1260번] 화학물질2  (0) 2019.04.27
[1257번] K번째 문자열  (0) 2019.04.21
[17135번] 케슬 디펜스  (0) 2019.04.11
[14923번] 미로 탈출  (0) 2019.04.09
[SwExpertAcademy] 비밀  (0) 2019.04.04