연구소 3 #파이썬

이동호·2022년 10월 15일
0

배울점: 바이러스가 활성으로만 되고 퍼뜨리는 상황이 없을때 이걸 타임에 넣어주면 안되기 때문에 이 문제를 해결하는 것이 핵심이었다. 이 문제를 graph를 보면서 바이러스가 가득찬 상황이라면 빠져나오게 하고 그렇지 않으면 계속 나아가도록 하였다. 이 생각을 했냐 못했냐가 핵심이었고 그 다음으로는 한번 틀렸었는데 핵심을 이번에는 0이 없는 상황인데 벽으로 가득차서 없는 상황이면 시간이 1일 수도 있기 때문에 이 상황에서는 0을 출력하도록 하였다. 그리고 시간을 최대한 짧게 되도록 최적화하는 것도 무척 중요했다.

import sys
import copy
from collections import deque
from itertools import combinations

def debug(graph):
  print()
  for i in range(1,n+1):
    for j in range(1,n+1):
      print(graph[i][j], end=' ')
    print()
  print()

def check(graph):
  flag=False
  #O(n^2) = 2500
  for i in range(1,n+1):
    for j in range(1,n+1):
      if graph[i][j] == 0:
        flag=True
        break
  return flag
  
dx=[1,-1,0,0]
dy=[0,0,1,-1]

input=sys.stdin.readline

n, m = map(int,input().split())
graph=[[0]*(1+n) for _ in range(1+n)]
virus=[]
for i in range(1,n+1):
  a=list(map(int,input().split()))
  a=[0]+a
  for j in range(1,n+1):
    #바이러스라면
    if a[j]==2:
      virus.append((i,j))
      graph[i][j] = -2
    #bfs에서 간편성을 위해서 바꿔줌
    elif a[j] == 1:
      graph[i][j] = -1
    else:
      graph[i][j] = a[j]
    
    
      
#activates는 활성 바이러스들의 가능한 조합
activates=list(combinations(virus, m))
INF=int(1e9)
mintime=INF

#10C5=189
for activate in activates:
  #2500 * 189
  copygraph=copy.deepcopy(graph)
  q=deque()
  # worst 5, 189 * 5
  for virus in activate:
    #queue에 virus 위치 장전
    q.append(virus)
    x, y = virus
    copygraph[x][y] = 1
  # 하나의 경우의 수마다의 걸리는 시간
  locmax=0
  while q:
    flag=True
    x, y = q.popleft()
    for i in range(4):
      nx = x + dx[i]
      ny = y + dy[i]
      if not (1<=nx<=n and 1<=ny<=n ) or copygraph[nx][ny] == -1 or copygraph[nx][ny] >0:
        continue
        #worst 10 * 2500, 10*2500*189
      if copygraph[nx][ny] == -2:
        flag=check(copygraph)
        # 0이 하나라도 없으면
        if not flag:
          locmax=max(locmax,copygraph[x][y])
          break
      copygraph[nx][ny] = copygraph[x][y] + 1
      locmax = max(locmax, copygraph[nx][ny])
      q.append((nx,ny))
    if not flag:
      break
  # 0이 하나라도 있으면 즉 바이러스 퍼뜨리는데 실패한 상황
  if check(copygraph):
    continue
  #debug(copygraph)
  mintime=min(mintime, locmax)

if mintime == INF:
  print(-1)
else:
    #정말로 바이러스가 처음부터 다 퍼져있었는데 벽으로 둘러쌓여있던 경우
  if mintime == 0:
    print(mintime)
  else:
    #시작을 1부터 했으므로
    print(mintime-1)
profile
안녕

0개의 댓글