본문 바로가기

알고리즘/BOJ

15683번

15683번 - 감시


상반기 대기업 SW 역량 평가로 나왔는데, 풀었던 문제였다. 


브루트포스로 하나씩 문제를 쪼개면 풀 수 있는 문제였다. 나는 실제 시험장에서 fill_map을 makeMap 함수안에 각각 구현해서 코드가 굉장


히 더러웠었던 기억이 난다ㅋㅋㅋ


일단 모든 CCTV를 90도로 돌려가면서, 최소의 사각지대를 만들어야 한다. 그래서 재귀함수로 모든 케이스를 탐색하도록 구현했다.


근데 일단 조금이라도 속도를 줄이고자, 90도로 돌렸을 때 나올 수 있는 가짓수를 dir_num 배열에 넣어줬다.


CCTV 1번은 4방향이 모두 다르다, 하지만 CCTV 2번 같은 경우에는 2가지 경우만 존재하고, 5번 같은 경우에는 1가지 경우만 존재한다.


그리고 이를 통해서 getMIN 함수에서 for문으로 몇가지 방법으로 돌릴지 정해서 for문을 구성했다.


makeMap 함수에서는 if 문을 통해서 노가다로 각 방향에 맞게 케이스를 나누어 주었다. 이것도 배열로 막 하려고 했는데 머리가 아파서 그냥


각 케이스를 if문을 이용해서 넣어주었다.


그리고 중요한 점은 add_val 값을 100으로 했는데, 처음에 단순하게 1로 해주고 -1로 원상복귀해주는 방식으로 했더니


CCTV 1번 번호도 map 에서 1이기 때문에 약간 겹치는 것 같아서 아예 큰 숫자인 100, -100으로 브루트 포스를 진행했다.


정답을 구하는 ans 변수는 사각지대의 최대 갯수는 n,m 의 최대 갯수가 8개 이므로 8*8인 64개를 넘지 않을 것이라 생각하여 좀 더 큰 수인 


100으로 초기화를 시켜서 문제를 풀었다.



<정답 코드>


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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include<iostream>
#include<vector>
using namespace std;
int dir_num[6= { 0,4,2,4,4,1 };
int n, m, ans;
int map[8][8];
vector<pair<intint>> cctv;
 
//실질적으로 맵을 채우는 함수.
void fill_map(int x,int y,int dx,int dy,int add_val)
{
    int nx = x + dx;
    int ny = y + dy;
 
    //벽과 CCTV 이외의 지점에서 add_val 만큼 더해줌.
    while (nx >= 0 && ny >= 0 && nx < n && ny < m && map[nx][ny] != 6)
    {
        if (map[nx][ny] == 0 || map[nx][ny]>=100)
        {
            map[nx][ny] += add_val;
        }
 
        nx +=dx;
        ny += dy;
    }
}
 
//맵을 어느 방향으로 채울 것인가 정하는 함수
void makeMap(int x,int y, int number, int d,int add_val)
{
    if (number == 1) {
        if (d == 0) {
            fill_map(x, y, 01,add_val);
        }
        if (d == 1) {
            fill_map(x, y, 10, add_val);
        }
        if (d == 2) {
            fill_map(x, y, 0-1, add_val);
        }
        if (d == 3) {
            fill_map(x, y, -10, add_val);
        }
    }
    
    if (number == 2) {
        if (d == 0) {
            fill_map(x, y, 01, add_val);
            fill_map(x, y, 0-1, add_val);
        }
        if (d == 1) {
            fill_map(x, y, 10, add_val);
            fill_map(x, y, -10, add_val);
        }
    }
 
    if (number == 3) {
        if (d == 0) {
            fill_map(x, y, -10, add_val);
            fill_map(x, y, 01, add_val);
        }
        if (d == 1) {
            fill_map(x, y, -10, add_val);
            fill_map(x, y, 0-1, add_val);
        }
        if (d == 2) {
            fill_map(x, y, 10, add_val);
            fill_map(x, y, 01, add_val);
        }
        if (d == 3) {
            fill_map(x, y, 10, add_val);
            fill_map(x, y, 0-1, add_val);
        }
    }
 
    if (number == 4) {
        if (d == 0) {
            fill_map(x, y, -10, add_val);
            fill_map(x, y, 01, add_val);
            fill_map(x, y, 0-1, add_val);
        }
        if (d == 1) {
            fill_map(x, y, 0-1, add_val);
            fill_map(x, y, 10, add_val);
            fill_map(x, y, -10, add_val);
        }
        if (d == 2) {
            fill_map(x, y, 01, add_val);
            fill_map(x, y, 0-1, add_val);
            fill_map(x, y, 10, add_val);
        }
        if (d == 3) {
            fill_map(x, y, 01, add_val);
            fill_map(x, y, 10, add_val);
            fill_map(x, y, -10, add_val);
        }
    }
 
    if (number == 5) {
        fill_map(x, y, 01, add_val);
        fill_map(x, y, 0-1, add_val);
        fill_map(x, y, 10, add_val);
        fill_map(x, y, -10, add_val);
    }
}
 
//사각지대를 구하는 함수
int getSize()
{
    int ret = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            if (map[i][j] == 0)
                ret++;
 
 
    return ret;
}
void getMIN(int cctv_num)
{
    //cctv 갯수만큼 구했을 때 최소값 구하기
    if (cctv_num == cctv.size())
    {
        int cur_size = getSize();
        if (cur_size < ans)
            ans = cur_size;
 
        return;
    }
 
 
    int x = cctv[cctv_num].first;
    int y = cctv[cctv_num].second;
    int number = map[x][y];
 
    //각 CCTV 마다 90도 회전할 수 있는 경우만큼 for문
    for (int i = 0; i < dir_num[number]; i++)
    {
        makeMap(x, y, number, i, 100);
        getMIN(cctv_num + 1);
        makeMap(x, y, number, i, -100);
 
 
    }
 
}
int main()
{
    //freopen("input.txt", "r", stdin);
    ans = 100;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];
 
            //CCTV에 해당하는 좌표 vector 에 추가
            if (map[i][j] >= 1 && map[i][j] <= 5)
                cctv.push_back({ i,j });
        }
    
    getMIN(0);
 
    cout << ans << endl;
 
 
    return 0;
}
cs


반응형

'알고리즘 > BOJ' 카테고리의 다른 글

2636번  (0) 2018.07.14
12761번  (0) 2018.07.14
15685번  (0) 2018.06.18
15686번  (0) 2018.06.14
1799번  (4) 2018.04.13