티스토리 뷰

# 문제

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


# 풀이

완전탐색을 통해 풀었습니다.


일단, CCTV의 종류와 위치를 따로하여서 vector에 저장했습니다.

그 후에 모든 CCTV를 돌면서 CCTV가 감시할 수 있는 모든방향을 검사하여 사각지대를 찾습니다.


CCTV의 종류마다 감시하는 구역이 중복되는 것을 눈치 채셨나요?

저는 1번, 3번,4번 카메라는 4방향 모두 돌려서 확인을 해주어야 되지만, 2번은 두번만 5번은 회전을 하지 않게끔 처리하였습니다.


dfs() 에서는 인자로 cnt를 가지고 있습니다.
이 인자는 현재 몇번째 CCTV까지 검사하였는지 나타냅니다.
그렇다면 재귀 함수의 종료 조건은 쉽게 찾아 낼 수 있겠죠?
저는 
cnt > (int)cctv.size()-1 일때! 종료 하게끔 만들어 주었습니다.


88번째 라인과 91번째 라인에서 왜 'MapCopy' 함수를 호출해서 'temp' 라는 이차원 배열에 저장을 할까요?

바로 모든 CCTV의 방향을 검사하기 위해서 입니다.


만약 4×4 라는 공간에 [1,1] 과 [3,1]에 1번 카메라가 있다고 해봅시다.


[초기 Map]

0

0

0


1번째 카메라가 [1,1]이고 2번째 카메라가 [3,1]가 vector에 저장되게 됩니다.
모든 카메라의 방향은 위부터 시작하며 오른쪽, 아래, 왼쪽 순으로 돌아간다고 가정을 합시다.


첫번째 카메라가 위를 비춘다면 아래의 표와 같아집니다.


[1번째 Map]

9

0

0

0


그 후 두번째 카메라 또한 위를 비추면 다음과 같아집니다.


[2번째 Map]

0

0

0

그러고 난 뒤 모든 카메라가 비추어졌으니 사각지대를 계산을 합니다.


다음 경우의 수는 두번째 카메라가 오른쪽을 비추는 것인데 [2번째 Map]를 그대로 사용한다면 위쪽과 오른쪽을 동시에 비춘것이 되기 때문에 [1번째 Map]으로 초기화를 해주어야 됩니다.

따라서 'MapCopy' 함수는 카메라를 비추기 이전의 상황으로 돌아가기 위해 만들어 놓은 것입니다.

처음에 제출했을때 런타임 에러가 떠버렸습니다....
왜 그런지 친구랑 찾는데... 저어어기 종료 조건에서 그런거였습니다 :(

cnt == cctv.size() 는 또 잘되었습니다.
앞에 형변환을 붙이니까 지금 코드도 잘 되더군요;;;
왜그럴까요... 'size' 메소드가 unsigned long형을 반환해서 그런걸까요...?
앞으로는 저런 식으로 코딩을 하면 안되겠습니다.. 다른 변수 저장하고 해야할듯...


# 코드

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
#include <iostream>
#include <vector>
 
#define MAX 8
#define INF 987654321
 
using namespace std;
 
int map[MAX][MAX];
 
vector<int> cctv;
vector<pair<intint>> cctvLocation;
 
int N,M;
int ans = INF;
 
void MapCopy(int (*a)[MAX], int (*b)[MAX]){
    for(int i = 0; i < N; i++){
        for(int j = 0; j < M; j++){
            a[i][j] = b[i][j];
        }
    }
}
 
void spread(int dir, int x, int y){
    //상
    if(dir == 0){
        int ny = y-1;
        if(ny < 0) return;
        if(map[ny][x] == 6) return;
        map[ny][x] = 9;
        spread(0, x, ny);
    }
    //우
    else if(dir == 1){
        int nx = x+1;
        if(nx > M-1) return;
        if(map[y][nx] == 6) return;
        map[y][nx] = 9;
        spread(1, nx, y);
    }
    //하
    else if(dir == 2){
        int ny = y+1;
        if(ny > N-1) return;
        if(map[ny][x] == 6) return;
        map[ny][x] = 9;
        spread(2, x, ny);
    }
    //좌
    else{
        int nx = x-1;
        if(nx < 0) return;
        if(map[y][nx] == 6) return;
        map[y][nx] = 9;
        spread(3, nx, y);
    }
}
 
void check(){
    int cnt = 0;
    for(int i = 0; i < N; i++){
        for(int j = 0; j < M; j++){
            if(map[i][j] == 0){
                cnt += 1;
            }
        }
    }
    if(cnt < ans)
        ans = cnt;
}
 
void dfs(int cnt){
    if(cnt > (int)cctv.size()-1){
        //사각지대 검사
        check();
        return;
    }
    int kind = cctv[cnt];
    int x = cctvLocation[cnt].first;
    int y = cctvLocation[cnt].second;
    
    int temp[MAX][MAX];
    
    //1번 cctv는 4방향
    if(kind == 1){
        for(int i = 0; i < 4; i++){
            MapCopy(temp, map);
            spread(i, x, y);
            dfs(cnt+1);
            MapCopy(map, temp);
        }
    }
    //2번 cctv는 2방향
    else if (kind == 2){
        for(int i = 0; i < 2; i++){
            MapCopy(temp, map);
            spread(i, x, y);
            spread(i+2, x, y);
            dfs(cnt+1);
            MapCopy(map, temp);
        }
    }
    //3번 cctv는 4방향
    else if(kind == 3){
        for(int i = 0; i < 4; i++){
            MapCopy(temp, map);
            spread(i, x, y);
            spread((i+1)%4, x, y);
            dfs(cnt+1);
            MapCopy(map, temp);
        }
    }
    //4번 cctv는 4방향
    else if(kind == 4){
        for(int i = 0; i < 4; i++){
            MapCopy(temp, map);
            spread(i, x, y);
            spread((i+1)%4, x, y);
            spread((i+2)%4, x, y);
            dfs(cnt+1);
            MapCopy(map, temp);
        }
    }
    //5번 cctv는 방향 변경x
    else{
        MapCopy(temp, map);
        for(int i = 0; i < 4; i++){
            spread(i, x, y);
        }
        dfs(cnt+1);
        MapCopy(map, temp);
    }
}
 
int main(){
    cin >> N >> M;
    for(int i = 0; i < N; i++){
        for(int j = 0; j < M; j++){
            int temp;
            cin >> temp;
            map[i][j] = temp;
            if(temp != 0 && temp != 6){
                cctv.push_back(temp);
                cctvLocation.push_back(make_pair(j, i));
            }
        }
    }
    dfs(0);
    cout << ans << endl;
    return 0;
}
 
cs


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

[BOJ 16235] 나무 재테크  (0) 2018.10.24
[BOJ 16236] 아기 상어  (0) 2018.10.23
[백준 15686] 치킨 배달  (0) 2018.07.03
백준 14503: 로봇 청소기  (0) 2018.01.19
백준 14500: 테트로미노  (0) 2018.01.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
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
글 보관함