solved_ac[Class4][치즈](https://www.acmicpc.net/problem/2638)
N×M의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다. 단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다. 이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다. 그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도 2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다. 따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.
<그림 1>
<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다. 그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다. 그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.
<그림 2>
<그림 3>
모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다. 입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오.
첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표시된다. 또한, 각 0과 1은 하나의 공백으로 분리되어 있다.
출력으로는 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 정수로 첫 줄에 출력한다.
8 9
0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0
0 0 0 1 1 0 1 1 0
0 0 1 1 1 1 1 1 0
0 0 1 1 1 1 1 0 0
0 0 1 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
4
[백준]1260번: DFS와 BFS의 업그레이드 문제이다. 앞서 풀었던 미로찾기와 비슷한데 여기서 추가된 것은 벽을 한번은 뚫을 수 있다는 것이다. 무조건 한번을 뚫어야 되는 것이 아닌 필요에 의해서 뚫을수도 있고 안뚫을수도 있다는 얘기이다. 이게 많이 복잡하다. 여기서 key 포인트는 벽을 안뚫고 갈때와 벽을 뚫고 갈때를 구분해서 작성을 해야 된다는 것이다. 그리고 또한 미로찾기에서는 graph를 직접 업데이트 해가면서 마지막 배열의 값이 총 걸리는 거리를 의미했는데 여기서는 graph를 직접 업데이트 시켜주면 안된다. 방문한 곳의 숫자가 증가해 있어서 이걸 벽으로 보고 못 지나갈 수 있기 때문에 다른 리스트를 이용하여 업데이트 시켜줘야한다. 그리고 또한 정답을 출력할 때 visited 리스트를 루프를 돌아 0이 아닌 리스트를 찾아 맨 마지막 리스트의 값을 출력할 필요가 없다. 어차피 최단 경로이기 때문에 bfs 루프를 돌다가 queue에서 가장 먼저 popleft()가 되어 나오는 좌표가 맨 오른쪽 밑의 좌표와 같다면 그것이 가장 최단 경로의 좌표인 것이다. 하지만 bfs 루프를 전부 돌았는데도 아무것도 return이 되는 것이 없다면 끝의 좌표에 도달하지 못한것이기 때문에 -1을 return 해주면서 정답을 도출해내면 된다.
import sys
from collections import deque
N, M = map(int, sys.stdin.readline().split())
graph = [[0] * M for _ in range(N)]
visited = [[0] * M for _ in range(N)]
for i in range(N):
graph[i] = list(map(int, sys.stdin.readline().split()))
queue = deque()
queue.append([0, 0])
visited[0][0] = 0
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
def bfs():
while queue:
x, y = queue.popleft()
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 graph[nx][ny] >= 1 and visited[x][y] <=1:
graph[nx][ny] += 1
elif visited[nx][ny] == 0 and graph[nx][ny] == 0:
queue.append([nx, ny])
visited[nx][ny] = 1
visited[x][y] += 1
count = 0
exit_check = 0
while True:
bfs()
for i in range(N):
for j in range(M):
visited[i][j] = 0
if graph[i][j] >= 3:
graph[i][j] = 0
exit_check = 1
queue.append([i, j])
elif graph[i][j] == 2:
graph[i][j] = 1
if exit_check == 1:
count += 1
else:
print(count)
break
exit_check = 0
bfs를 시작할때 어떤 것을 기준으로 할지 중요하게 생각하게 되었다. 처음에는 치즈를 기준으로 bfs를 시작했었는데 코드가 너무 난잡해지고 조건이 많아져서 외부를 기준으로 bfs를 하였다. 그렇게 하고 하니 내부 공기를 굳이 신경 쓰지 않더라도 알아서 치즈가 막아주기 때문에 bfs가 내부 공기가 있는 곳으로 들어가서 검사를 하지 않았다. 그리고 한타임이 지나면 치즈들이 녹아 없어지는데 그곳에도 많은 조건이 숨겨져 있었다. 풀기 전에 모든 조건을 완벽하게 글로 써서 슈도 코드를 작성하고 코딩을 해야겠다..