728x90
    
    
  문제링크
https://www.acmicpc.net/problem/14502
- 문제 이해하는 데도 상당히 오랜 시간이 걸린 문제이다
 - 0 갯수를 최대화 할 수 있도록 1을 3개 세워야하는 문제이다
 - 2가 탐색 방식으로 확장해나가는 구조라 생각하면 좀 더 쉽게 생각이 가능하다
- 1이 나올때 까지 0을 2로 바꿔버린다
 
 
해설
- 이 문제야 말로 컴퓨터가 인간보다 잘 푸는 유형의 대표적인 예라고 생각한다
 - 전체 조합을 모두 고려해야하는 상황에서는 dfs를 먼저 생각할 줄 알아야 한다
 
풀이과정
- 3개의 벽을 골라 벽을 설치한다
 - 각 바이러스가 사방으로 퍼지는 것을 DFS/BFS로 계산하여 안전 영역을 구한다
 
전체 코드
dx = (-1, 0, 1, 0)
dy = (0, 1, 0, -1)
result = 0
def is_valid_coord(x, y):
    return 0 <= x < n and 0 <= y < m
# 깊이 우선 탐색(DFS)를 이용해 각 바이러스가 사방으로 퍼지도록 하기
def virus(x, y):
    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]
        if is_valid_coord(nx, ny):
            if temp[nx][ny] == 0:
                # 해당 위치에 바이러스 배치하고, 재귀적으로 수행
                temp[nx][ny] = 2
                virus(nx, ny)
# 현재 맵에서 안전 영역의 크기 계산하는 메서드
def get_score():
    score = 0
    for i in range(n):
        for j in range(m):
            if temp[i][j] == 0:
                score += 1
    return score
# 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매번 안전 영역의 크기 계산
def dfs(count):
    global result
    
    # 울타리가 3개 설치된 경우
    if count == 3:
        for i in range(n):
            for j in range(m):
                temp[i][j] = graph[i][j]
            # 각 바이러스의 위치에서 전파 진행
            for i in range(n):
                for j in range(m):
                    if temp[i][j] == 2:
                        virus(i, j)
            
            # 안전 영역의 최댓값 계산
            result = max(result, get_score())
            return
        
    # 빈 공간에 울타리 설치
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                graph[i][j] = 1
                count += 1
                dfs(count)
                graph[i][j] = 0
                count -= 1
dfs(0)
print(result)
다른 풀이
from collections import deque
import copy
import sys
input = sys.stdin.readline
def bfs():
    queue = deque()
    tmp_graph = copy.deepcopy(graph)
    for i in range(n):
        for j in range(m):
            if tmp_graph[i][j] == 2:
                queue.append((i, j))
    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                continue
            if tmp_graph[nx][ny] == 0:
                tmp_graph[nx][ny] = 2
                queue.append((nx, ny))
    global answer
    cnt = 0
    for i in range(n):
        cnt += tmp_graph[i].count(0)
    answer = max(answer, cnt)
def makeWall(cnt):
    if cnt == 3:
        bfs()
        return
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                graph[i][j] = 1
                makeWall(cnt+1)
                graph[i][j] = 0
n, m = map(int, input().split())
graph = []
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
for i in range(n):
    graph.append(list(map(int, input().split())))
answer = 0
makeWall(0)
print(answer)
총평/느낀점
- 이제 어느정도는 DFS/BFS로 풀어야하는 유형을 구분할 수 있게 된 것 같다.
 - 너무 어렵다..
 
출처
- 이것이 코딩테스트다
 
728x90
    
    
  'PYTHON > CODING TEST' 카테고리의 다른 글
| [DFS/BFS] 타겟넘버 (0) | 2024.05.12 | 
|---|---|
| [DFS/BFS] 특정 거리의 도시 찾기 (1) | 2024.05.12 | 
| [DFS/BFS] 미로 탈출 (0) | 2024.05.10 | 
| [DFS/BFS] 음료수 얼려 먹기 (0) | 2024.05.10 | 
| [programmers] 카드 뭉치 (0) | 2023.02.19 |