전형적인 DFS/BFS 문제이다. 전체 맵의 크기가 크지 않다. 최대 8X8 크기의 맵에서 바이러스의 최소 갯수는 2 이므로, 벽을 세울 수 있는 최대 연산해야 하는 조합의 수는 61C3 = 35990 이다. 100000번 보다 작은 수 이기 때문에 제한시간 2초안에 충분히 모든 경우를 계산해 풀 수 있는 부르트 포스 알고리즘 문제이다.
실제로 예전에 몇 번 코딩테스트를 봤을 때 자주 봤던 유형이다. 필수적으로 풀 줄 알아야 하는 유형이라고 생각한다!
벽을 놓는 조합을 구하는 방법과 바이러스를 퍼지게 하는 방법에 모두 BFS 또는 DFS를 사용할 수 있다. 파이썬을 사용하는 경우 조합을 구하는 Permutations 모듈을 사용할 수도 있다.
나는 혼자 풀이할 때 벽을 놓는데 DFS, 바이러스 확산에 BFS를 사용하고 조합 라이브러리를 이용한 풀이도 제출해봤다. 라이브러리를 이용하는 것이 약간 더 빨랐다.
하지만 다른 사람들의 코드를 보니 내 코드가 현저히 느리게 동작했다. 일단 조합을 구하는 내 코드가 비효율적인 것 같다.
from collections import deque import sys n, m = map(int,input().split()) no_safe = 3 board = [] virus = [] for i inrange(n): board.append(list(map(int, sys.stdin.readline().rstrip().split()))) for j inrange(m): if board[i][j] == 2: virus.append((i,j)) no_safe +=1 elif board[i][j] == 1: no_safe +=1
dx = [0,1,0,-1] dy = [1,0,-1,0]
defcheck(board): visited = [[False]*m for _ inrange(n)] result = n*m - no_safe for v in virus: vx,vy = v[0],v[1] q = deque([(vx,vy)]) visited[vx][vy]==1 while q: cur = q.popleft() x,y = cur[0],cur[1] for d inrange(4): nx,ny = x+dx[d], y+dy[d] if0<=nx<n and0<=ny<m and board[nx][ny]==0and visited[nx][ny]==False: visited[nx][ny] = True result-=1 q.append((nx,ny)) return result
defsol(board,n_wall,last_i,last_j,ans): if n_wall == 0: return check(board) for j inrange(last_j,m): if board[last_i][j]==0: board[last_i][j]=1 new_ans= sol(board, n_wall-1, last_i, j,ans) ans = max(ans, new_ans) board[last_i][j] = 0 for i inrange(last_i+1,n): for j inrange(m): if board[i][j]==0: board[i][j]=1 new_ans= sol(board, n_wall-1, i, j,ans) ans = max(ans, new_ans) board[i][j]=0 return ans
from collections import deque from itertools import combinations import sys n, m = map(int,input().split()) no_safe = 3 board = [] virus = [] safe = [] for i inrange(n): board.append(list(map(int, sys.stdin.readline().rstrip().split()))) for j inrange(m): if board[i][j] == 2: virus.append((i,j)) no_safe +=1 elif board[i][j] == 1: no_safe +=1 else: safe.append((i,j))
dx = [0,1,0,-1] dy = [1,0,-1,0]
defcheck(board): visited = [[False]*m for _ inrange(n)] result = n*m - no_safe for v in virus: vx,vy = v[0],v[1] q = deque([(vx,vy)]) visited[vx][vy]==1 while q: cur = q.popleft() x,y = cur[0],cur[1] for d inrange(4): nx,ny = x+dx[d], y+dy[d] if0<=nx<n and0<=ny<m and board[nx][ny]==0and visited[nx][ny]==False: visited[nx][ny] = True result-=1 q.append((nx,ny)) return result
defsol(): ans = -1 for permu in combinations(safe, 3): for p in permu: board[p[0]][p[1]] = 2 cal = check(board) ans = max(cal, ans) for p in permu: board[p[0]][p[1]] = 0 return ans