득이공간

[백준 C++] 15683 감시 - 백트래킹 본문

PS/알고리즘 문제풀이

[백준 C++] 15683 감시 - 백트래킹

쟁득 2024. 4. 26. 12:25

 

15683번: 감시

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

www.acmicpc.net


 

문제풀이

 

구현할 것이 많은 시뮬레이션 & 브루트포스 & 백트래킹 유형의 문제입니다.

 

카메라의 개수는 많지 않기 때문에, 각 카메라의 방향을 완전탐색(브루트포스 & 백트래킹)으로

모든 각도에서 지정해보고 그 중 사각지대의 최소값을 구하면 됩니다.

 

사각지대를 구하기 전에 각 카메라의 방향에 따른 사무실의 상태를 구할 때 많은 구현이 필요합니다.

각 카메라가 사무실을 스캔할 때, 카메라의 종류에 따라 먼저 분류하고

지정된 스캔 방향, 횟수에 따라서 사무실의 상태를 구하도록 했습니다.


코드

cpp
#include <iostream> #include <cstring> using namespace std; typedef pair<int, int> p; typedef pair<int, p> info; const int DX[4] = { -1, 0, 1, 0 }; const int DY[4] = { 0, -1, 0, 1 }; int N, M; int Map[8][8]; int C; info Cam[8]; int Dir[8]; int Min; int Sol[8][8]; void Scanning(int Idx, int D, int MulInverse = 1) { int R = Cam[Idx].second.first, C = Cam[Idx].second.second; int i = 1; while (true) { ‌‌int NR = R + DY[D] * i * MulInverse; ‌‌int NC = C + DX[D] * i * MulInverse; ‌‌if (NR < 0 || NR > N - 1 || NC < 0 || NC > M - 1 ‌‌‌|| Sol[NR][NC] == 6) ‌‌{ ‌‌‌break; ‌‌} ‌‌if (Sol[NR][NC] == 0) ‌‌{ ‌‌‌Sol[NR][NC] = -1; ‌‌} ‌‌++i; } } int CountBlank() { memcpy(Sol, Map, sizeof(Sol)); for (int i = 0; i < C; ++i) { ‌‌int D = Dir[i]; ‌‌int D2 = (D + 1 > 3) ? 0 : D + 1; ‌‌switch (Cam[i].first) ‌‌{ ‌‌case 1: ‌‌‌Scanning(i, D); ‌‌‌break; ‌‌case 2: ‌‌‌Scanning(i, D); ‌‌‌Scanning(i, D, -1); ‌‌‌break; ‌‌case 3: ‌‌‌Scanning(i, D); ‌‌‌Scanning(i, D2); ‌‌‌break; ‌‌case 4: ‌‌‌Scanning(i, D); ‌‌‌Scanning(i, D, -1); ‌‌‌Scanning(i, D2); ‌‌‌break; ‌‌case 5: ‌‌‌Scanning(i, D); ‌‌‌Scanning(i, D, -1); ‌‌‌Scanning(i, D2); ‌‌‌Scanning(i, D2, -1); ‌‌‌break; ‌‌} } int Cnt = 0; for (int i = 0; i < N; ++i) { ‌‌for (int j = 0; j < M; ++j) ‌‌{ ‌‌‌if (Sol[i][j] == 0) ‌‌‌{ ‌‌‌‌++Cnt; ‌‌‌} ‌‌} } return Cnt; } void Backtracking(int Idx) { if (Idx == C) { ‌‌Min = min(Min, CountBlank()); ‌‌return; } for (int i = 0; i < 4; ++i) { ‌‌Dir[Idx] = i; ‌‌Backtracking(Idx + 1); } } int main() { ‌ios::sync_with_stdio(false); ‌cin.tie(nullptr); cout.tie(nullptr); ‌cin >> N >> M; ‌Min = N * M; for (int i = 0; i < N; ++i) { ‌‌for (int j = 0; j < M; ++j) ‌‌{ ‌‌‌int Num; ‌‌‌cin >> Num; ‌‌‌Map[i][j] = Num; ‌‌‌if (Num >= 1 && Num <= 5) ‌‌‌{ ‌‌‌‌Cam[C] = info(Num, p(i, j)); ‌‌‌‌++C; ‌‌‌‌--Min; ‌‌‌} ‌‌‌else if (Num == 6) ‌‌‌{ ‌‌‌‌--Min; ‌‌‌} ‌‌} } Backtracking(0); ‌cout << Min; }