백준 15683 - 감시
삼성 SW 역량 테스트 기출 문제들을 쭉 풀어보기로 했다.
이번 문제는 백준 골드 4 문제 감시 문제이다.
문제를 한 번 차근차근 읽어보자.
5종류의 CCTV가 있고, 각 CCTV를 회전시켜보는 문제이다.
CCTV를 회전시켜 사각지대가 최소가 되는 경우를 요구하고 있다.
이 때, 사무실의 크기는 최대 8x8
이고, CCTV는 6개까지 가능하다.
내가 생각하기엔 직접 모든 경우를 찾아야 될 것 같다.
각 CCTV는 5번을 제외하면 4방향으로 돌릴 수 있는데, 한 번 생각해보자.
CCTV의 위치는 이미 고정되어 있고, 모든 CCTV의 조합을 생각해보면?
4^6 = 4096
가지의 경우가 나온다.
그리고 매 조합 사이사이에 사각지대를 계산하기 위해 이중 for문을 돌리면,
O(N^2)
일 때, 최대 N이 8로 그렇게 오랜 시간이 걸리지 않을 것 같다.
한 번 직접 구현을 해보도록 하자.
만약 시간초과가 발생하면, 그 때 가서 고쳐도 된다.
완전 탐색
우선, CCTV의 가시 거리를 표시하기 이전에 방향을 어떻게 설정할까?
각 CCTV 별 방향의 모든 조합을 둘러볼 수 있어야 한다.
CCTV의 수만큼 탐색을 진행하며, 매 탐색마다 CCTV의 방향을 설정할 수 있을까?
먼저, 재귀를 통해서 각 깊이마다 CCTV의 방향을 설정하고자 했다.
배열을 하나 만들어, 각 CCTV의 방향을 정한 뒤 저장해놓는다.
CCTV의 수 만큼의 깊이에 도달했을 때 해당 방향 조합을 한 번에 이용할 수 있다.
위의 코드대로 구현했으며, 이는 Backtracking 방식을 사용한다.
흔히 순열, 조합을 뽑을 때 백트래킹을 사용하는데, 동일한 방식이다.
그럼, 해당 방향 조합대로 가시 범위는 어떻게 표시할까?
이 방식 또한 재귀를 사용해서 일자로 쭉 깊이 파고들도록 해보자.
위 코드와 같이 구현했다.
위 함수로 매번 가시 범위를 그린 다음, 사각지대를 계산하도록 했다.
하지만 곧바로 메모리 초과가 발생했다.
시간 초과가 아닌 메모리 초과가 뜬다? 이 부분은 조금 이해가 안됐다.
아마 재귀 방식이 stack 메모리를 사용하기 때문에 발생한 것 같은데,
특정 예제에서 재귀를 너무 많이 돈다는 말이 된다.
잠시 반례에 대해 생각을 조금 해보니, edge case를 하나 빼먹었다.
CCTV가 아예 없을 때 내 코드는 무한히 재귀를 들어가게 된다.
그래서, 재귀 중지 조건을 CCTV를 모두 탐색했을 때가 아닌,
깊이가 CCTV의 갯수보다 많아졌을 때로 고쳤다.
이렇게 되면 CCTV가 없을 때 바로 함수를 종료하게 된다.
결국 해냈다!
삼성 SW 역량 문제를 차근차근 풀다보니 어지러운 구현 문제가 좀 많은 것 같다.
시간 복잡도를 반드시 고민하며 풀어야 할 문제들인 것 같고,
최대한 시간을 줄이려는 아이디어도 필요할 것 같다.