|
| 1 | +# 백준 15683번: 감시 (2회차) |
| 2 | + |
| 3 | +import sys |
| 4 | + |
| 5 | +input = sys.stdin.readline |
| 6 | + |
| 7 | +# N, M <= 8 |
| 8 | +N, M = map(int, input().rstrip().split()) |
| 9 | +maps = [list(map(int, input().rstrip().split())) for _ in range(N)] |
| 10 | +watchs = [[0 for _ in range(M)] for _ in range(N)] |
| 11 | + |
| 12 | +# 0은 빈 칸 |
| 13 | +# 1~5는 CCTV (<= 8개) |
| 14 | +# 6은 벽 |
| 15 | +EMTPY = 0 |
| 16 | +WALL = 6 |
| 17 | + |
| 18 | +cctvs = [] |
| 19 | +emptys = 0 |
| 20 | +for r in range(N): |
| 21 | + for c in range(M): |
| 22 | + if maps[r][c] == EMTPY: |
| 23 | + emptys += 1 |
| 24 | + elif maps[r][c] < WALL: |
| 25 | + cctvs.append((maps[r][c], r, c)) |
| 26 | +# for row in maps: |
| 27 | +# print(row) |
| 28 | +# print() |
| 29 | + |
| 30 | +# 브루트포싱: |
| 31 | +# 1. 8개의 CCTV가 4개 방향 = 4^8 = 2^16 <= 10^5 |
| 32 | +# 2. 각 CCTV 방향마다 8개 칸 |
| 33 | +# 10^6 안쪽으로 통과할 것으로 기대 |
| 34 | + |
| 35 | +directions_per_cctv_types = { |
| 36 | + 1: [ |
| 37 | + [0], |
| 38 | + [1], |
| 39 | + [2], |
| 40 | + [3] |
| 41 | + ], |
| 42 | + 2: [ |
| 43 | + [0, 2], |
| 44 | + [1, 3] |
| 45 | + ], |
| 46 | + 3: [ |
| 47 | + [0, 1], |
| 48 | + [1, 2], |
| 49 | + [2, 3], |
| 50 | + [3, 0] |
| 51 | + ], |
| 52 | + 4: [ |
| 53 | + [0, 1, 2], |
| 54 | + [1, 2, 3], |
| 55 | + [2, 3, 0], |
| 56 | + [3, 0, 1] |
| 57 | + ], |
| 58 | + 5: [ |
| 59 | + [0, 1, 2, 3] |
| 60 | + ], |
| 61 | +} |
| 62 | +moves = [ |
| 63 | + [-1, 0], |
| 64 | + [0, 1], |
| 65 | + [1, 0], |
| 66 | + [0, -1] |
| 67 | +] |
| 68 | + |
| 69 | +def is_valid_position(r, c): |
| 70 | + return 0 <= r < N and 0 <= c < M |
| 71 | + |
| 72 | +def print_maps(): |
| 73 | + for r in range(N): |
| 74 | + for c in range(M): |
| 75 | + if watchs[r][c] > 0: print('*', end='') |
| 76 | + elif maps[r][c] == WALL: print('#', end='') |
| 77 | + elif maps[r][c] == EMTPY: print('.', end='') |
| 78 | + else: print(maps[r][c], end='') |
| 79 | + print() |
| 80 | + print() |
| 81 | + |
| 82 | +def bruteforcing(idx): |
| 83 | + # print(f'bruteforcing({idx})') |
| 84 | + global emptys, answer |
| 85 | + |
| 86 | + if idx >= len(cctvs): |
| 87 | + # print(f'---- searched: {emptys} ----') |
| 88 | + # print_maps() |
| 89 | + answer = min(answer, emptys) |
| 90 | + return |
| 91 | + |
| 92 | + cctv_type, cctv_r, cctv_c = cctvs[idx] |
| 93 | + for views in directions_per_cctv_types[cctv_type]: |
| 94 | + # print('views:', views) |
| 95 | + # 각 시야각 별 감시 시작 |
| 96 | + for direction in views: |
| 97 | + # print('direction:', direction) |
| 98 | + r, c = cctv_r, cctv_c |
| 99 | + dr, dc = moves[direction] |
| 100 | + while is_valid_position(r + dr, c + dc) and maps[r + dr][c + dc] < WALL: |
| 101 | + r, c = r + dr, c + dc |
| 102 | + if not watchs[r][c] and maps[r][c] == EMTPY: |
| 103 | + emptys -= 1 |
| 104 | + watchs[r][c] += 1 |
| 105 | + # 다음 CCTV 브루트포싱 |
| 106 | + bruteforcing(idx + 1) |
| 107 | + # 감시 해제 |
| 108 | + for direction in views: |
| 109 | + r, c = cctv_r, cctv_c |
| 110 | + dr, dc = moves[direction] |
| 111 | + while is_valid_position(r + dr, c + dc) and maps[r + dr][c + dc] < WALL: |
| 112 | + r, c = r + dr, c + dc |
| 113 | + watchs[r][c] -= 1 |
| 114 | + if not watchs[r][c] and maps[r][c] == EMTPY: |
| 115 | + emptys += 1 |
| 116 | + |
| 117 | +answer = int(1e9) |
| 118 | +bruteforcing(0) |
| 119 | +print(answer) |
0 commit comments