Game Develop

[Algorithm] Baekjoon 15683번 : 감시 본문

Algorithm/Baekjoon

[Algorithm] Baekjoon 15683번 : 감시

MaxLevel 2023. 12. 28. 05:15

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

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감

www.acmicpc.net

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
 
 
using namespace std;
 
struct Node
{
    int y;
    int x;
};
 
int n, m;
int arr[9][9= { 0 };
vector<Node> camPositions;
 
vector<vector<vector<int>>> camDirs =
{
    {{0}},
    {{1},{2},{3},{0}},
    {{1,3},{0,2 }},
    {{0,1},{1,2},{2,3},{3,0} },
    {{3,0,1},{0,1,2}, {1,2,3},{2,3,0} },
    {{0,1,2,3}}
};
 
int dirs[4][2= { {-1,0}, {0,1}, {1,0}, {0,-1} };
 
vector<int> curDirs;
int zeroCount = 0;
int answer = 0x3f3f3f3f;
 
 
void DFS(int index)
{
    if (index == camPositions.size())
    {
        bool visited[9][9= { false };
        int tempCount = zeroCount;
 
        for (int i = 0; i < camPositions.size(); ++i)
        {
            int curY = camPositions[i].y;
            int curX = camPositions[i].x;
            int camNum = arr[curY][curX];
            visited[curY][curX] = true;
 
            for (int j = 0; j < camDirs[camNum][curDirs[i]].size(); ++j)
            {
                int curDir = camDirs[camNum][curDirs[i]][j];
                int nextY = curY + dirs[curDir][0];
                int nextX = curX + dirs[curDir][1];
 
                while (1)
                {
                    if (nextY < 0 || nextY == n) break;
                    if (nextX < 0 || nextX == m) break;
                    if (arr[nextY][nextX] == 6break;
 
                    if (visited[nextY][nextX] == false)
                    {
                        if (arr[nextY][nextX] == 0)
                        {
                            --tempCount;
                            visited[nextY][nextX] = true;
                        }
                        else // 카메라면 걍 넘어가기
                        {
                            visited[nextY][nextX] = true;
                        }
                    }
 
                    nextY += dirs[curDir][0];
                    nextX += dirs[curDir][1];
                    
                }
            }
        }
 
        answer = min(answer, tempCount);
        return;
    }
 
    int camNum = arr[camPositions[index].y][camPositions[index].x];
    for (int i = 0; i < camDirs[camNum].size(); ++i)
    {
        curDirs.push_back(i);
        DFS(index + 1);
        curDirs.pop_back();
    }
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    cin >> n >> m;
 
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            cin >> arr[i][j];
 
            if (arr[i][j] == 0)
            {
                ++zeroCount;
            }
            else if (arr[i][j] >= 1 && arr[i][j] <= 5)
            {
                camPositions.push_back({ i,j });
            }
        }
    }
 
    DFS(0);
 
    cout << answer;
}
cs
 

 

각 카메라타입에 따른 방향을 전부 룩업테이블에 정리해주고, 카메라회전에 대한 경우의수를 전부 DFS로 뽑아서 검사해주면 된다. 

모든 카메라가 4번회전하는게 아니라는걸 유의하자. 1번카메라는 한가지방향밖에 감시를 못해서 네방향에 대해 경우의 수를 뽑아야하지만, 2번카메라는 '한번에' 위아래, 혹은 좌우를 검사할 수 있기 때문에 인덱스계산에 안헷갈리도록 유의하자.