알고리즘

[백준] 15683. 감시 - python

hseoky 2024. 4. 4. 11:01
728x90

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

 

15683번: 감시

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

www.acmicpc.net

 

난이도: 골드4

알고리즘: 백트래킹

 

 

풀이과정

최대 크기가 8 x 8이고 CCTV가 최대 8개이므로 전수조사가 가능하다.

 

CCTV의 위치들을 저장하고 각 CCTV의 모든 경우에 대해 사각지대의 개수를 조사한다.

 

방문처리를 할 때 7을 더하고 방문취소를 할 때 7을 빼는 방식으로 수행하고 모든 CCTV에 대해 방문처리가 진행되면 board에서 값이 0인 칸 수를 세서 현재 가장 적은 사각지대인 answer와 비교한다.

 

소스코드

def set_visit(y, x, dy, dx, num):
    global board
    ny = y + dy
    nx = x + dx
    while 0 <= ny < N and 0 <= nx < M and board[ny][nx] != 6:
        if (ny, nx) not in cctv_pos:
            board[ny][nx] += num
        ny += dy
        nx += dx


def backtracking(idx):
    if idx == len(cctv_pos):
        global answer
        count = 0
        for i in range(N):
            for j in range(M):
                if board[i][j] == 0:
                    count += 1
        answer = min(answer, count)
        return

    y, x = cctv_pos[idx]
    if board[y][x] == 1:
        for i in range(4):
            # 방문 처리
            set_visit(y, x, dy[i], dx[i], 7)
            backtracking(idx + 1)
            # 방문 취소
            set_visit(y, x, dy[i], dx[i], -7)
    elif board[y][x] == 2:
        for i in range(2):
            set_visit(y, x, dy[i], dx[i], 7)
            set_visit(y, x, dy[i + 2], dx[i + 2], 7)
            backtracking(idx + 1)
            set_visit(y, x, dy[i], dx[i], -7)
            set_visit(y, x, dy[i + 2], dx[i + 2], -7)
    elif board[y][x] == 3:
        for i in range(4):
            set_visit(y, x, dy[i], dx[i], 7)
            set_visit(y, x, dy[(i + 1) % 4], dx[(i + 1) % 4], 7)
            backtracking(idx + 1)
            set_visit(y, x, dy[i], dx[i], -7)
            set_visit(y, x, dy[(i + 1) % 4], dx[(i + 1) % 4], -7)
    elif board[y][x] == 4:
        for i in range(4):
            set_visit(y, x, dy[i], dx[i], 7)
            set_visit(y, x, dy[(i + 1) % 4], dx[(i + 1) % 4], 7)
            set_visit(y, x, dy[(i + 2) % 4], dx[(i + 2) % 4], 7)
            backtracking(idx + 1)
            set_visit(y, x, dy[i], dx[i], -7)
            set_visit(y, x, dy[(i + 1) % 4], dx[(i + 1) % 4], -7)
            set_visit(y, x, dy[(i + 2) % 4], dx[(i + 2) % 4], -7)
    elif board[y][x] == 5:
        for i in range(4):
            set_visit(y, x, dy[i], dx[i], 7)
        backtracking(idx + 1)
        for i in range(4):
            set_visit(y, x, dy[i], dx[i], -7)


N, M = map(int, input().split())
board = [[0 for _ in range(M)] for _ in range(N)]
cctv_pos = []
dy = [1, 0, -1, 0]
dx = [0, 1, 0, -1]
answer = 100
for i in range(N):
    row = list(map(int, input().split()))
    for j in range(M):
        if row[j] != 0 and row[j] != 6:
            cctv_pos.append((i, j))
        board[i][j] = row[j]
backtracking(0)
print(answer)

 

728x90