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

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net


내 풀이

 

from itertools import combinations

n, m = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(n)]
tmp = [[0]*m for _ in range(n)]

def virus(x, y):
    dx = [1,0,-1,0]
    dy = [0,1,0,-1]
    
    for k in range(4):
        xx = x+dx[k]
        yy = y+dy[k]
        if 0<=xx<n and 0<=yy<m and tmp[xx][yy] == 0:
            tmp[xx][yy] = 2
            virus(xx, yy)


def count():
    cnt = 0
    for i in range(n):
        for j in range(m):
            if tmp[i][j] == 0:
                cnt += 1
    return cnt


def solution():
    result = 0
    

    
    zeroIdxs = []
    for i in range(n):
        for j in range(m):
            if board[i][j] == 0:
                zeroIdxs.append((i, j))

    for coordinates in list(combinations(zeroIdxs, 3)):
        
        for x,y in coordinates:
            board[x][y] = 1

        
        for i in range(n):
            for j in range(m):
                tmp[i][j] = board[i][j]

        
        for i in range(n):
            for j in range(m):
                if tmp[i][j] == 2:
                    virus(i, j)

        result = max(result, count())
       
        for x,y in coordinates:
            board[x][y] = 0
    return result


print(solution())

이 문제 푸려고 진짜 오래고민했다. 거의 이주는 고민한듯..

근데 오늘 비슷한 유형의 문제를 풀면서 이해했다 드디어!

 

이 문제의 핵심이 무엇이냐

1) 벽을 세울 수 있는 모든 지점에 벽을 세운다. -> solution()을 통해

2) 바이러스를 모두 퍼뜨린다 -> virus() 을 통해

3) 넓이를 구한다.  -> count() 을 통해

4) 넓이를 구해서 최대값과 비교한다.  

5) 모든 경우의 수에 반복한다.

 

 


다른사람의 풀이

 

import sys
import copy
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

N, M = map(int,input().split())
graph = [list(map(int,input().split())) for _ in range(N)] # 그래프 생성
graph_copy = copy.deepcopy(graph) # 그래프 복사
dx, dy = [-1,1,0,0], [0,0,-1,1] # 상하좌우 이동

safe_region = 0 # 최대 안전 영역

# dfs
def dfs(x,y,sel_wall):
    sel_wall[x][y] = 2 # 바이러스로 변경

    # 상하좌우 탐색
    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]
        if 0 <= nx < N and 0 <= ny < M:
            if sel_wall[nx][ny] == 0: # 바이러스가 퍼질 수 있는 곳
                dfs(nx,ny,sel_wall) # 바이러스 퍼뜨리기


# 벽 선택하기
def select_wall(start, count):
    global safe_region

    if count == 3: # 벽이 3개 선택된 경우 실행
        sel_wall = copy.deepcopy(graph_copy) # 벽이 선택된 그래프 복사
        # dfs로 바이러스 퍼뜨리기
        for i in range(N):
            for j in range(M):
                if sel_wall[i][j] == 2: # 바이러스 발견시에 dfs
                    dfs(i,j,sel_wall)
        safe_count = sum(_.count(0) for _ in sel_wall) # 안전 영역 개수 계산
        safe_region = max(safe_region,safe_count) # 최대 안전 영역 개수 갱신
        return

    else: # 벽이 3개 선택되지 않은 경우
        for i in range(start, N*M): # 브루트-포스로 벽 선택
            r = i // M # M으로 나눈 몫는 행
            c = i % M # M으로 나눈 나머지는 열
            if graph_copy[r][c] == 0: # 해당 구역이 0인 경우에
                graph_copy[r][c] = 1 # 벽으로 선택
                select_wall(i,count+1) # 다음 벽 선택
                graph_copy[r][c] = 0 # 되돌리기

select_wall(0,0)
print(safe_region)


COMBINATION을 사용하지 않고도 풀이가 가능할거 같은데, 파이썬으로 돌리면 시간초과가 난다.

그 부분에 대해서는 조금 고민 해봐야 할거같다.

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

11725 - 파이썬  (0) 2022.08.17
2468 - 파이썬  (0) 2022.08.16
16326 - 파이썬  (0) 2022.08.02
1707 - 파이썬  (0) 2022.08.02
16928 - 파이썬  (0) 2022.08.01

+ Recent posts