15863 - 감시

2023. 6. 21. 23:54·백준

 


 

문제

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

 

15683번: 감시

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

www.acmicpc.net

 

풀이

완탐 + 구현문제이다.

 

첫번째로 cctv 종류와 cctv위치를 배열에 저장한다.

 

다음으로 cctv별로 회전할 수 있는 경우의 수를 모두 구한다. 나는 일관성을 가지기 위하여 모두 4방향으로 회전한다고 가정했으며 [ 0, 1, 2, 3 => 우, 하, 좌, 상 ] 순으로 정의했다. 이 때 itertools product를 통하여 모든 경우의 수를 만들었다.

 

마지막으로 3차원 배열을 정의한다. 코드상에서 cctv_d 배열이며,

cctv_d[cctv종류][방향] 값을 넣어주면 감시해야하는 방향이 들어있는 1차원 배열을 얻을 수 있다.

 

그리고 미리 정의해둔 탐색함수(search) 에 위치와 방향을 매개변수로 던져주고 감시 범위를 체크하면 된다.

 

코드

import copy
import itertools
from sys import stdin
import sys

def search(x, y, d):
    global dx, dy, n, m, temp

    while True:
        nx = x + dx[d]
        ny = y + dy[d]

        # 범위 안에 있으며 벽이 아니라면
        if 0 <= nx < n and 0 <= ny < m and temp[nx][ny] != 6:
            # 빈칸일경우 방문처리 해준다. cctv면 그냥 넘어가면 된다.
            if temp[nx][ny] == 0:
                temp[nx][ny] = 9
            x = nx
            y = ny
        else:
            break


# Initialize
n, m = map(int, input().split())
office = [ list(map(int, stdin.readline().rstrip().split())) for _ in range(n)]
cctvs = []
answer = sys.maxsize
for i in range(n):
    for j in range(m):
        if office[i][j] != 0 and office[i][j] != 6:
            cctvs.append([office[i][j], [i, j]])

# cctv 회전의 모든 경우의 수
directions = itertools.product([0, 1, 2, 3], repeat=len(cctvs))

# 우 하 좌 상 순서
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]


# cctv_d[cctv번호][경우의 수 방향]
cctv_d = [
    [[]],
    [[0], [1], [2], [3]],
    [[0, 2], [1, 3], [0, 2], [1, 3]],
    [[0, 1], [1, 2], [2, 3], [3, 0]],
    [[3, 0, 1], [0, 1, 2], [1, 2, 3], [2, 3, 0]],
    [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
]

# 특정 그래프를 탐색하려면, 좌표와 방향을 지시해주어야 한다.
for dire in directions:
    temp = copy.deepcopy(office)
    # 해당 사이즈는 cctv 크기와 같다.
    for j in range(len(dire)):
        # 각 cctv와 회전에 맞게 값을 넣어준다.
        for val in cctv_d[cctvs[j][0]][dire[j]]:
            x, y = cctvs[j][1]
            search(x, y, val)

    temp_ans = 0
    for i in range(n):
        for j in range(m):
            if temp[i][j] == 0:
                temp_ans += 1

    # for v in temp:
    #     print(v)
    # print()
    answer = min(answer, temp_ans)



print(answer)

 

후기

 

탐색부분에 있어 잘하면 최적화를 더 할 수 있을 거 같긴 하다, 중복되는 부분이 워낙 많다보니 말이다.

 

근데 그렇게 생각하니 더 머리 아파서, 무식하지만 브루트포스로 풀었다.. 제한범위가 워낙 작다보니 가능했던 거 같다.

'백준' 카테고리의 다른 글

16235 - 나무 재테크  (0) 2023.06.23
15864 - 사다리 조작  (0) 2023.06.23
3190 - 뱀  (0) 2023.06.21
1010 - 다리 놓기  (0) 2023.06.19
12865 - 평범한 배낭  (1) 2023.06.19
'백준' 카테고리의 다른 글
  • 16235 - 나무 재테크
  • 15864 - 사다리 조작
  • 3190 - 뱀
  • 1010 - 다리 놓기
whiporithm
whiporithm
https://github.com/whipbaek
  • whiporithm
    whiporithm
    whiporithm
  • 전체
    오늘
    어제
    • 분류 전체보기 (176)
      • 개발 (17)
      • LeetCode (3)
      • 백준 (79)
      • 프로그래머스 (64)
      • 회고 (6)
      • 쉘 스크립트 (4)
      • 자바 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    알고리즘
    쉘
    쉘스크립트
    카카오코딩테스트
    파이썬코테
    자바알고리즘
    코테
    자바
    nestjs 배포
    파이썬알고리즘
    프로그래머스
    개발
    파이썬
    백준
    파이썬코딩테스트
    코딩테스트
    자바코테
    카카오
    Java
    카카오코테
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
whiporithm
15863 - 감시
상단으로

티스토리툴바