일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- programmers
- DP
- 프로그래머스
- 알고리즘
- DVWA
- 문자열
- 완전탐색
- 코딩테스트
- 동적계획법
- graph
- Queue
- Code Refactoring
- DFS
- 정렬
- 큐
- Dynamic Programming
- 탐욕법
- django
- 그래프
- sort
- BFS
- Brute Force
- Algorithm
- Greedy
- 힙
- 백준
- binary search
- string
- 카카오 기출
- heap
- Today
- Total
생각과 고민이 담긴 코드
백준 - 연구소 (DFS, BFS, 완전탐색) / Gold 5 / 14502번 본문
문제 : https://www.acmicpc.net/problem/14502
14502번: 연구소
인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크
www.acmicpc.net
풀이
import sys
from itertools import combinations
from copy import deepcopy
def virus(row, col):
if row > 0 and map_lab[row - 1][col] == 0:
map_lab[row - 1][col] = 2
virus(row - 1, col)
if row < N - 1 and map_lab[row + 1][col] == 0:
map_lab[row + 1][col] = 2
virus(row + 1, col)
if col > 0 and map_lab[row][col - 1] == 0:
map_lab[row][col - 1] = 2
virus(row, col - 1)
if col < M - 1 and map_lab[row][col + 1] == 0:
map_lab[row][col + 1] = 2
virus(row, col + 1)
return
def safe_spot():
cnt = 0
for i in range(N):
for j in range(M):
if map_lab[i][j] == 0:
cnt += 1
return cnt
N, M = map(int, sys.stdin.readline().split())
lab_map = []
result = []
for _ in range(N):
lab_map.append(list(map(int, sys.stdin.readline().split())))
spot = []
for i in range(N):
for j in range(M):
if lab_map[i][j] == 0:
spot.append([i, j])
cases = list(combinations(spot, 3))
for case in cases:
map_lab = deepcopy(lab_map)
for i in case:
map_lab[i[0]][i[1]] = 1
for i in range(N):
for j in range(M):
if map_lab[i][j] == 2:
virus(i, j)
result.append(safe_spot())
print(max(result))
정말 오랜 시간을 들여 결국 혼자 힘으로 푼 문제이다.
이 문제의 알고리즘은 다음과 같은 순서로 동작한다.
- 벽 세우기.
- 바이러스 퍼뜨리기.
- 0의 개수 세기.
2번과 3번은 사실 구현만 하면 된다.
즉, 시간복잡도에 큰 영향을 주진 않는다.
다만 1번의 "벽을 어떤식으로 세우냐"에 대한 알고리즘은 생각해야 한다.
먼저 벽을 세우는 모든 경우의 수를 완전탐색 할 수 있는지 입력 크기를 통해 확인하여야 한다.
이건 항상 알고리즘 문제를 풀 때 필수적으로 해야 하는 행동이다.
지도의 최대 크기가 8X8이기에 64칸이고 바이러스가 최소라 가정, 2를 빼면 62칸이다.
모든 칸에 벽을 놓을 수 있다고 가정하고 62칸에 벽 3개를 놓는 경우의 수는 62C3이다.
다른 단계의 시간복잡도를 고려하더라도 완전탐색이 충분히 가능하다고 보았다.
바이러스 퍼뜨리기는 재귀함수를 이용하여 DFS로 구현하였다.
(이 과정에서 문제과 관련 없지만 기억할만한 내용은
map_lab라는 2차원 배열이 mutable 객체이기 때문에
함수 인자로 넣어주지 않아도 index를 통해 값을 변경할 수 있었다.
그러나 map_lab 변수를 재할당 할 때에는 lab_map 2차원 배열을 깊은 복사로 복사하여
객체 안에 요소들까지 완전히 새로운 주소 값을 갖도록 하였다.)
'Algorithm > 백준' 카테고리의 다른 글
백준 - 단지번호붙이기 (DFS/BFS) / Silver 1 / 2667번 (0) | 2021.11.22 |
---|---|
백준 - 치킨 배달 (완전 탐색) / Gold 5 / 15686번 (0) | 2021.11.21 |
백준 - 트리의 부모 찾기 (DFS, BFS) / Silver 2 / 11725번 (0) | 2021.11.17 |
백준 - 물건 팔기 (정렬, 완전 탐색) / Silver 3 / 1487번 (0) | 2021.11.12 |
백준 - 연산자 끼워넣기 (완전 탐색) / Silver 1 / 14888번 (0) | 2021.11.02 |