λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Algorithm/λ°±μ€€(BOJ)

[ 파이썬(python) ] λ°±μ€€ 4179 - 뢈! (BFS)

by YWTechIT 2021. 4. 22.
728x90

πŸ“Œ λ°±μ€€ 4179 - 뢈!

문제 μ„€λͺ…


πŸ’‘ λ‚˜μ˜ 풀이

λ‚˜μ—κ² λ”μ°ν•œ λ¬Έμ œμ˜€λ‹€.. 이 λ¬Έμ œμ— μ˜€μ „, μ˜€ν›„λ₯Ό μ™„μ „νžˆ μŸμ•„λ²„λ Έλ‹€. πŸ˜‡ πŸ˜‡ 수 없이 μ½”λ“œλ₯Ό μ œμΆœν–ˆλ‹€. ν•˜μ§€λ§Œ, λŒμ•„μ˜€λŠ” λŒ€λ‹΅μ€ 인덱슀 μ—λŸ¬ ν˜Ήμ€ ν‹€λ ΈμŠ΅λ‹ˆλ‹€. 채점 쀑간에 71%μ—μ„œ 자꾸 μ˜€λ‹΅ νŒμ •μ„ λ°›μ•˜λ‹€.

 

 

ν‹€λ¦° 이유λ₯Ό λ‹¨κ³„λ³„λ‘œ μž‘μ„±ν•˜λ©΄

  1. 인덱슀 μ—λŸ¬(Index Error): λ³€μˆ˜ μ •μ˜ λ‹¨κ³„μ—μ„œ ν–‰κ³Ό 열을 λ°˜λŒ€λ‘œ μž…λ ₯ν–ˆλ‹€.
  2. 잘λͺ»λœ λ³€μˆ˜ μž…λ ₯: 넀이밍을 λΉ„μŠ·ν•˜κ²Œ ν•΄μ„œ κ·ΈλŸ°μ§€ 쀑간에 λ‹€λ₯Έ λ³€μˆ˜λ₯Ό μž‘μ„±ν•΄μ„œ μ œμΆœν–ˆλ‹€.
  3. 잘λͺ»λœ μ½”λ“œ: μ—¬κΈ°μ„œ μ‹œκ°„μ΄ 제일많이 κ±Έλ ΈλŠ”λ° λ§ˆμ§€λ§‰ 단계인 f_visited > j_visited 쑰건을 잘λͺ» μΆ”κ°€ν–ˆλ‹€. μ²˜μŒμ—λŠ” f_visited[nx][ny] > j_visited[nx][ny]둜 μƒκ°ν–ˆλŠ”λ° μ•„λ‹ˆμ—ˆλ‹€. μ™œ κ·ΈλŸ°κ°€ ν•˜λ©΄ μš°λ¦¬κ°€ fire BFSλ‹¨κ³„μ—μ„œ μ„ μ–Έν–ˆλ˜ f_visited[nx][ny] = f_visited[x][y] + 1λ₯Ό λ– μ˜¬λ €λ³΄μž.
728x90

문제λ₯Ό ν’€λ©΄μ„œ λ„μ €νžˆ 감이 μž‘νžˆμ§€ μ•ŠλŠ”λ‹€λ©΄ 핡심 파트λ₯Ό μ‚΄νŽ΄λ³΄μž.

  1. 뢈(fire)κ³Ό μ§€ν›ˆμ΄μ˜ queueλ₯Ό 2개 μ„ μ–Έν•˜κ³  λ°©λ¬Έ 기둝도 λ§ˆμ°¬κ°€μ§€λ‘œ 2개 μ„ μ–Έν•œλ‹€.(f_queue, j_queue / f_visited, j_visited)
  2. μ§€ν›ˆμ΄μ™€ λΆˆμ€ 맀 λΆ„λ§ˆλ‹€ 상, ν•˜, 쒌, 우둜 퍼진닀.
  3. μ§€ν›ˆμ΄κ°€ λΆˆμ— κ°‡νžˆμ§€ μ•Šκ³  μ•ˆμ „ν•˜κ²Œ νƒˆμΆœν•˜λ €λ©΄ 뢈이 퍼진 μ‹œκ°„λ³΄λ‹€ μ§€ν›ˆμ΄κ°€ μ΄λ™ν•œ μ‹œκ°„μ΄ 더 빨라야 ν•œλ‹€.
  4. λ‹€μ‹œ 말해, ν•œ μ’Œν‘œμ˜ 값을 κΈ°μ€€μœΌλ‘œ λΆˆλ³΄λ‹€ μ§€ν›ˆμ΄μ˜ 값이 더 크닀면 κ·Έμͺ½μœΌλ‘œ 움직일 수 μ—†λ‹€.
  5. μ§€ν›ˆμ΄λŠ” 미둜의 κ°€μž₯μžλ¦¬μ— μ ‘ν•œ κ³³μ—μ„œ νƒˆμΆœν•œλ‹€κ³  λ‚˜μ™€μžˆλŠ”λ°, μ΄λŠ” (nx, ny) μ’Œν‘œκ°€ 미둜의 λ²”μœ„λ₯Ό λ²—μ–΄λ‚  λ•Œ νƒˆμΆœμ΄ κ°€λŠ₯ν•˜λ‹€.
  6. BFS λ‚΄λΆ€μ—μ„œ queueλŠ” 거리순으둜 λˆ„μ λœλ‹€λŠ” 점을 κΈ°μ–΅ν•˜μž.
  7. μ§€ν›ˆμ΄κ°€ 미둜λ₯Ό λΉ μ Έλ‚˜μ˜€μ§€ λͺ»ν•œ κ²½μš°λŠ” while문이 μ’…λ£Œλ  λ•ŒκΉŒμ§€λ„ 좜λ ₯이 μ—†λŠ” κ²½μš°λ‹ˆκΉŒ κ·Έλ•ŒλŠ” IMPOSSIBLE을 좜λ ₯ν•˜μž.

 

 

또, λ‹€λ₯Έ μ‚¬λžŒμ˜ 풀이λ₯Ό μ°Ύμ•„λ³΄λ‹ˆκΉŒ λ‹€λ“€ λ²”μœ„μ— λ“€μ–΄μ˜€μ§€ μ•ŠλŠ” 경우둜만 κ΅¬ν•΄μ„œ μ μž–μ΄ λ‹Ήν™©ν–ˆμ—ˆλ‹€. λ‚˜λŠ” λŒ€μ²΄λ‘œ BFS λ¬Έμ œλŠ” λ²”μœ„μ— λ“€μ–΄μ˜€λŠ” 경우둜만 κ³„μ‚°ν–ˆκΈ° λ•Œλ¬Έμ— μ•„λ‹Œ 경우λ₯Ό μ°ΎλŠ” μ½”λ“œλŠ” 손에 읡지 μ•Šμ•˜λ‹€.

 

λ‚΄κ°€ μˆ˜μ‹­ 번의 μ½”λ“œλ₯Ό λ‹€μ‹œ μ œμΆœν–ˆλ˜ μ΄μœ λŠ” 28번 μ½”λ“œμΈλ° λ‹¨μˆœν•˜κ²Œ nx, ny μ’Œν‘œμ—μ„œ 뢈이 λ°©λ¬Έν•œ κ²½λ‘œμ™€ μ§€ν›ˆμ΄κ°€ λ°©λ¬Έν–ˆλ˜ 경둜만 λΉ„κ΅ν•˜λ©΄ 될 쀄 μ•Œμ•˜λ”λ‹ˆ 그게 μ•„λ‹ˆμ—ˆλ‹€. ν”Όλ‚˜λŠ” ꡬ글링 끝에 얻은 λ°˜λ‘€ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό κ°€μ Έμ™”λ‹€. μ™œ λŒ€μ†Œλ§Œ λΉ„κ΅ν•˜λ©΄ μ•ˆ λ˜λŠ”μ§€ 같이 μ‚΄νŽ΄λ³΄μž.

 

'''
3 4
###F
.J#.
###.
'''

 

ν˜„μž¬ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ—μ„œ f_visited와 j_visited의 κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  1. f_visited = [[0, 0, 0, 1], [0, 0, 0, 2], [0, 0, 0, 3]]
  2. j_visited = [[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0]]

μ΄μƒν•˜λ‹€. λΆ„λͺ… 뢈이 λ²ˆμ§€μ§€ μ•Šμ•˜κ³  벽도 μ•„λ‹Œλ° μ™œ j_visited[1][0] μžλ¦¬λŠ” 2둜 λ°”λ€Œμ§€ μ•Šμ€ 거지?!


κ·Έ μ΄μœ λŠ” 뢈이 λ°©λ¬Έν•˜μ§€ μ•Šμ€κ²½μš°(not f_visited[nx][ny] or)μ—λŠ” μ •μƒμ μœΌλ‘œ BFS처리λ₯Ό ν•΄μ€˜μ•Ό ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. μ € μ½”λ“œλ₯Ό λΉΌλ©΄ λ‹¨μˆœνžˆ 뢈이 λ°©λ¬Έν•œ κ²½λ‘œμ™€ μ§€ν›ˆμ΄κ°€ λ°©λ¬Έν•œ 경둜의 μ’Œν‘œλ§Œ λΉ„κ΅ν•΄μ„œ 더 큰 κ°’λ§Œ 좜λ ₯ν•˜κΈ° λ•Œλ¬Έμ— 뢈이 λ°©λ¬Έν•˜μ§€ μ•Šμ€ κ²½λ‘œλŠ” BFS μ²˜λ¦¬ν•˜μ§€ μ•ŠλŠ”λ‹€.

 

κ³¨λ“œ λ¬Έμ œμ— μ΅μˆ™ν•˜μ§€ μ•Šμ•„μ„œ κ·ΈλŸ°μ§€ λͺ¨λ₯΄κ² μ§€λ§Œ λ°˜λ‘€μ˜ μΌ€μ΄μŠ€μ˜ μ€‘μš”μ„±μ„ 이 문제λ₯Ό ν†΅ν•΄μ„œ 잘 μ•Œκ²Œ 됐닀. λ°±μ€€ μ§ˆλ¬Έκ²€μƒ‰μ—μ„œ 3개의 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό 더 κ°€μ Έμ™”λ‹€. ν˜Ήμ‹œλ‚˜ 풀리지 μ•ŠλŠ”λ‹€λ©΄ λ‹€μŒμ„ μ‹œλ„ν•΄λ³΄μž.

 

'''
5 5
....F
...J#
....#
....#
...#.

좜λ ₯: 4

---

3 3
F.F
.J.
F.F

좜λ ₯: IMPOSSIBLE

---

5 5
#####
#...#
#.J.#
#...#
#####

좜λ ₯: IMPOSSIBLE
'''

 

ν•˜λ‹¨μ˜ μ½”λ“œλŠ” 2개λ₯Ό κ°€μ Έμ™”λŠ”λ° λ²”μœ„λ₯Ό μ•ˆμͺ½μœΌλ‘œ μ„€μ •ν•œ μ½”λ“œ, λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜κ²Œ μ„€μ •ν•œ μ½”λ“œλ₯Ό κ°€μ Έμ™”λ‹€. λ‘˜ 쀑 이해가 μž˜λ˜λŠ” μ½”λ“œλ‘œ μ‚¬μš©ν•˜μž. λ‚˜λŠ” 첫 번째 μ½”λ“œκ°€ 이해가 더 μž˜λλ‹€.

 

아직 싀버 1밖에 λ˜μ§€ μ•Šμ•˜μ§€λ§Œ κ³¨λ“œ 문제 첫 신고식을 잘(?) 치λ₯Έ 것 κ°™λ‹€.
이제 λ‹€λ₯Έ κ³¨λ“œ 문제λ₯Ό ν’€λ©΄μ„œ 역경에 또 λΆ€λ”ͺν˜€λ³΄μž!

 

# in range case

import sys
from collections import deque
input = sys.stdin.readline

def bfs():
    while f_queue:    # fire BFS
        x, y = f_queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if 0 <= nx < R and 0 <= ny < C:
                if not f_visited[nx][ny] and graph[nx][ny] != '#':
                    f_visited[nx][ny] = f_visited[x][y] + 1
                    f_queue.append((nx, ny))

    while j_queue:    # jihoon BFS
        x, y = j_queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if 0 <= nx < R and 0 <= ny < C:
                if not j_visited[nx][ny] and graph[nx][ny] != '#':
                    if not f_visited[nx][ny] or f_visited[nx][ny] > j_visited[x][y] + 1:    # important code
                        j_visited[nx][ny] = j_visited[x][y] + 1
                        j_queue.append((nx, ny))
            else:
                return j_visited[x][y] + 1    # escape map

    return 'IMPOSSIBLE'    # not escape map

dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]

R, C = map(int, input().split())
graph = [list(input().strip()) for _ in range(R)]
f_queue, j_queue = deque(), deque()    # declare fire, jihoon queue
f_visited, j_visited = [[0] * C for _ in range(R)], [[0] * C for _ in range(R)]    # declare fire, jihoon visited

for i in range(R):
    for j in range(C):
        if graph[i][j] == 'F':
            f_queue.append((i, j))
        elif graph[i][j] == 'J':
            j_queue.append((i, j))
print(bfs())

 

# out range case(continue)

import sys
from collections import deque
input = sys.stdin.readline

def bfs():
    while f_queue:    # fire BFS
        x, y = f_queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or ny < 0 or nx >= R or ny >= C:
                continue

            if f_visited[nx][ny] != 0 or graph[nx][ny] == '#':
                continue

            f_visited[nx][ny] = f_visited[x][y] + 1
            f_queue.append((nx, ny))

    while j_queue:    # jihoon BFS
        x, y = j_queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or ny < 0 or nx >= R or ny >= C:
                return j_visited[x][y] + 1    # escape map

            if j_visited[nx][ny] != 0 or graph[nx][ny] == '#' or (f_visited[nx][ny] != 0 and f_visited[nx][ny] <= j_visited[x][y]+1):    # important code
                continue

            j_visited[nx][ny] = j_visited[x][y] + 1
            j_queue.append((nx, ny))

    return 'IMPOSSIBLE'    # not escape map

dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]

R, C = map(int, input().split())
graph = [list(input().strip()) for _ in range(R)]
f_queue, j_queue = deque(), deque()    # declare fire, jihoon queue
f_visited, j_visited = [[0] * C for _ in range(R)], [[0] * C for _ in range(R)]    # declare fire, jihoon visited

for i in range(R):
    for j in range(C):
        if graph[i][j] == 'F':
            f_queue.append((i, j))
        elif graph[i][j] == 'J':
            j_queue.append((i, j))
print(bfs())
λ°˜μ‘ν˜•

λŒ“κΈ€