- 문제 : https://www.acmicpc.net/problem/3055

 

Gold Lv4 문제이고, 풀이 없이 풀었다! 사실 이전에 풀었던 불 문제와 풀이가 비슷했다. 

 

문제 이해 

- 고슴도치(S)가 물이 번지는 상황에서 물에 잠기지 않고 무사히 비버 소굴(D)로 최소 시간에 갈 수 있는지 확인하는 문제다.

- 고슴도치와 물 둘 다 bfs로 진행해야하기 때문에 둘다 모두 queue에 넣어서 진행해야한다.

- 고슴도치는 matrix에서 '.', 'D'인 지점을 지날 수 있고, 물은 '.' 인 지점만 갈 수 있다.

하지만 시간을 아끼기 위해서는 고슴도치와 물 모두 각 지점이 ' . '이거나 'D'인 지점을 탐색할 수 있게 했다. (물은 'D' 지점을 못 가기 때문에 추가 조건을 달아준다, 이렇게 한 이유는 이전에 고슴도치, 물 각각 따로 분기문으로 나눠서 진행했는데 시간초과가 발생했기 때문이다)

- 고슴도치가 가는 길은 양의 정수로 진행하고, 물이 지나가는 곳은 -1 처리를 해서 고슴도치가 못가게 한다.

 

 

풀이 로직

- 입력값(n, m, matrix)을 입력받으면서 고슴도치의 위치, 비버 소굴의 위치, 물의 위치를 저장한다. 

- queue에 이동하는 위치를 추가할 건데, 이때 어떤 객체가 움직이는지 확인하기 위해 [행, 열, 'kaktus'(고슴도치)'], [행, 열, 'water'(물)]의 형태로 데이터를 추가한다. 

- 물의 위치는 queue에 입력하고, 고슴도치와 비버 소굴의 위치는 (a, b), (c, d)에 입력한다.

     - 고슴도치와 물의 초기 위치를 visit에 기록한다. (고슴도치는 visit[i][j] = 1, 물은 visit[i][j] = -1 -> 이렇게 초기 설정을 하지 않으면            틀리거나 시간초과가 발생한다)

     - 물(*)의 위치를 queue에 먼저 넣는 이유는 고슴도치는 물이 번질 곳으로는 이동하면 안되기 때문이다.

- while문을 진행하면서 도착한 위치가 비버 소굴이고, 객체가 고슴도치라면 정답이므로 답을 저장한 다음, flag = True 설정 후 break한다.

    - 답이 visit[x][y] - 1인 이유는 처음 시작을 1로 시작했기 때문에 정답보다 1 크기 때문이다.

- 아직 도착하지 않았다면 범위 내에서 상하좌우를 탐색한다. 이때 각 노드들은 다음 노드를 방문하지 않았고, matrix의 값이 '.' 또는 'D'인 지점만 방문 가능하다. 

- 고슴도치인 경우 visit[다음노드]로 시간 1을 들여 이동한다. 물이라면 matrix == '.' 인 지점만 이동 가능하고, visit[다음노드]를 -1 처리하고 이동한다. 

- 만약 반복문을 다 돌아도 flag == False 라면 실패한 것이므로 'KAKTUS'를 출력한다. 아니라면 그대로 정답을 출력하면 된다.

 

 

정답풀이 

n, m = map(int, input().split())
matrix = []
a, b = 0, 0 # 고슴도치 위치 
c, d = 0, 0 # 비버 소굴 위치
queue = []
visit = [[0] * m for _ in range(n)]
for i in range(n):
    matrix.append(list(input()))
    for j in range(m):
        if matrix[i][j] == 'D':
            c, d = i, j
        if matrix[i][j] == 'S':
            a, b = i, j
            visit[i][j] = 1
        if matrix[i][j] == '*':
            queue.append([i, j, 'water'])
            visit[i][j] = -1
            
queue.append([a, b, 'kaktus'])
dx, dy = [-1, 1, 0, 0], [0, 0, -1, 1]
answer = 0
flag = False
while queue:
    x, y, kind = queue.pop(0)
    
    if x == c and y == d:
        if kind == 'kaktus':
            flag = True
            answer = visit[x][y] - 1
            break
    
    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]
        if 0 <= nx < n and 0 <= ny < m:
            if not visit[nx][ny] and (matrix[nx][ny] == '.' or matrix[nx][ny] == 'D'):
                if kind == 'kaktus':
                    visit[nx][ny] = visit[x][y] + 1
                    queue.append([nx, ny, 'kaktus'])
                if kind == 'water':
                    if matrix[nx][ny] == '.':
                        visit[nx][ny] = -1
                        queue.append([nx, ny, 'water'])
                    
if flag == False :
    print('KAKTUS')
else:
    print(answer)

 

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

[bfs/백준] 9019번 : DSLR  (0) 2023.05.26
[bfs/백준] 16397번 : 탈출  (0) 2023.05.25
[bfs/백준] 5427번 : 불  (0) 2023.05.22
[bfs/백준] 2206번 : 벽 부수고 이동하기  (0) 2023.05.20
[bfs/백준] 16234번 : 인구 이동  (0) 2023.05.17

+ Recent posts