알고리즘/백준

백준-14502-연구소

hong2943 2024. 7. 1. 03:27
구현
import sys
from collections import deque

input = sys.stdin.readline

n , m = map(int, input().split())

temp = [[0] * m for _ in range(n)] # 벽 설치 후의 맵

# 초기 입력 받는 맵
graph = []
for i in range(n):
    graph.append(list(map(int,input().split())))

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

result = 0
# bfs를 이용해 바이러스가 퍼지는 상황 구현
def virus(x,y):
    queue = deque()
    queue.append((x,y))

    while queue:
        a,b = queue.popleft()

        # 4방향 확인
        for i in range(4):
            nx = a + dx[i]
            ny = b + dy[i]

            if nx < 0 or nx >=n or ny < 0 or ny >= m: # 범위 벗어나는 경우 
                continue
                
            # 벽 무시
            if temp[nx][ny] == 1:
                continue

            # 빈칸(0)은 2로 바꾼다
            if temp[nx][ny] == 0:
                temp[nx][ny] = 2
                queue.append((nx,ny))

#벽 세우기 
def wall(count):
    global result

    # 벽을 3개 세웠다면 바이러스를 퍼뜨린다.
    if count == 3:
        for i in range(n):
            for j in range(m):
                temp[i][j] = graph[i][j]

        # 2가 있는 곳이 bfs의 출발지점으로 하면 바이러스가 퍼지는 것 구현 가능
        for i in range(n):
            for j in range(m):
                if temp[i][j] == 2:
                    virus(i,j)

        #안전영역 개수 카운트
        safe = 0
        for i in range(n):
            for j in range(m):
                if temp[i][j] == 0:
                    safe += 1
        result = max(result, safe)
        return

    # 벽 세우기 ★★ 백트래킹!!
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                graph[i][j] = 1 # 벽 세운다
                count += 1
                wall(count) # 다음 벽을 세운다.
                graph[i][j] = 0 # wall에서 return후 들어간다.
                count -= 1 # 벽을 허무는 과정

wall(0)
print(result)
  • 해당 문제에서 중요한 부분은 벽을 세우는 부분을 구현하는 것이다
  • 이를 구현하기 위해서 DFS와 백 트래킹을 사용해야했다.
    • n x m 크기의 맵을 하나씩 순회하면서 빈칸(0)을 만나면 벽(1)을 세운다.
    • 벽은 3개를 세워야하기 때문에 벽을 하나 세우면 count+=1를 해준다.
    • count == 1일 때 wall함수가 호출되면 바이러스를 퍼뜨려 안전영역의 개수를 카운트
    • 그리고 다시 벽을 허물고 다른 경우의 수를 찾는다 [백트래킹]
    • 이 과정을 반복하며 전체 맵을 순회하고, 안전영역 최대값을 출
백트래킹 : 해를 찾는 도중 해가 아니어서 막히면, 되돌아가서 다시 해를 찾아가는 기법

virus함수 DFS로 구현

import sys
from collections import deque

input = sys.stdin.readline

n , m = map(int, input().split())

temp = [[0] * m for _ in range(n)] # 벽 설치 후의 맵

# 초기 입력 받는 맵
graph = []
for i in range(n):
    graph.append(list(map(int,input().split())))

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

result = 0
#DFS  바이러스가 퍼지는 상황 구현
def virus(x,y):
    # 4방향 확인
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]

        #범위 내부
        if nx >= 0 and nx <n and ny >= 0 and ny < m:
            if temp[nx][ny] == 0:
                temp[nx][ny] = 2
                virus(nx,ny)

#벽 세우기 
def wall(count):
    global result

    # 벽을 3개 세웠다면 바이러스를 퍼뜨린다.
    if count == 3:
        for i in range(n):
            for j in range(m):
                temp[i][j] = graph[i][j]

        # 2가 있는 곳이 bfs의 출발지점으로 하면 바이러스가 퍼지는 것 구현 가능
        for i in range(n):
            for j in range(m):
                if temp[i][j] == 2:
                    virus(i,j)

        #안전영역 개수 카운트
        safe = 0
        for i in range(n):
            for j in range(m):
                if temp[i][j] == 0:
                    safe += 1
        result = max(result, safe)
        return

    # 벽 세우기 ★★ 백트래킹!!
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                graph[i][j] = 1 # 벽 세운다
                count += 1
                wall(count) # 다음 벽을 세운다.
                graph[i][j] = 0 # wall에서 return후 들어간다.
                count -= 1 # 벽을 허무는 과정

wall(0)
print(result)

 

문제링크

'알고리즘 > 백준' 카테고리의 다른 글

백준-2839-설탕 배달  (1) 2024.07.03
백준-11497-통나무 건너뛰기  (0) 2024.07.03
백준-14248-점프 점프  (0) 2024.06.25
백준-1541-잃어버린 괄호  (0) 2024.06.18
백준-9095-1, 2, 3 더하기  (0) 2024.06.17