Problem Solving/[ν•­ν•΄99] TIL

99클럽 μ½”ν…Œ μŠ€ν„°λ”” 9일차 TIL / BFS(λ„ˆλΉ„ μš°μ„  탐색)

geum 2024. 11. 6. 09:14

✏️ 문제

https://www.acmicpc.net/problem/7562

 

체슀판 μœ„μ— ν•œ λ‚˜μ΄νŠΈκ°€ 놓여져 μžˆλ‹€. λ‚˜μ΄νŠΈκ°€ ν•œ λ²ˆμ— 이동할 수 μžˆλŠ” 칸은 μ•„λž˜ 그림에 λ‚˜μ™€μžˆλ‹€. λ‚˜μ΄νŠΈκ°€ μ΄λ™ν•˜λ €κ³  ν•˜λŠ” 칸이 주어진닀. λ‚˜μ΄νŠΈλŠ” λͺ‡ 번 움직이면 이 칸으둜 이동할 수 μžˆμ„κΉŒ?

 

πŸ€– μž…μΆœλ ₯ μ˜ˆμ‹œ

 

🧐 λ‚œμ΄λ„/μ†Œμš” μ‹œκ°„

βœ… λ‚œμ΄λ„: solved.ac κΈ°μ€€ S1

βœ… μ†Œμš” μ‹œκ°„: 28λΆ„ 44초

βœ… ꢌμž₯ μ‹œκ°„: 1μ‹œκ°„

 

πŸ’‘ 풀이

1) 문제 μœ ν˜• νŒŒμ•…

λ¬Έμ œμ— 주어진 κ·Έλ¦Όκ³Ό μ΅œμ†Œ 이동 횟수λ₯Ό ꡬ해야 ν•˜λŠ” κ±Έ 보고 BFS둜 ν’€μ–΄μ•Όκ² λ‹€κ³  μƒκ°ν–ˆλ‹€.

 

2) 아이디어 흐름

β‘  λ‚˜μ΄νŠΈκ°€ 움직일 수 μžˆλŠ” λ°©ν–₯ ν‘œν˜„

μ§€κΈˆκΉŒμ§€ λ³Έ BFS λ¬Έμ œλ“€μ€ 항상 λ­”κ°€λ₯Ό 2차원 리슀트 μœ„μ—μ„œ 움직여 닡을 μ°ΎλŠ” λ°©μ‹μ΄μ—ˆλ‹€. 이 λ¬Έμ œλ„ κ·Έ ν‹€μ—μ„œ λ²—μ–΄λ‚˜μ§„ μ•Šμ§€λ§Œ λ‹¨μˆœνžˆ μƒν•˜μ’Œμš°λ‘œ μ›€μ§μ΄λŠ” 게 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— dx, dy 배열을 λ§Œλ“€ λ•Œ 값을 잘 μž…λ ₯ν•΄μ£ΌλŠ” 게 μ€‘μš”ν•˜λ‹€.

 

총 μ—¬λŸ λ°©ν–₯으둜 움직일 수 있고 이동 κ°€λŠ₯ν•œ λ°©ν–₯은 (-2, -1, 1, 2)λ₯Ό μ‘°ν•©ν•΄ ν‘œν˜„ν•  수 μžˆλ‹€.

 

β‘‘ μ΄λ™ 횟수 계산

❎ move λ³€μˆ˜ ν™œμš©

첫 번째 μ‹œλ„λŠ” 이동 횟수λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ λ³€μˆ˜ 'move'λ₯Ό 0으둜 μ΄ˆκΈ°ν™”ν•˜κ³  체슀판 μ˜μ—­ μ•ˆμ— μžˆλŠ” 칸에 λŒ€ν•΄ νŠΉμ • 칸이 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ€ μƒνƒœμΌ λ•Œλ§ˆλ‹€ move += 1을 μˆ˜ν–‰ν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€.

 

이 방식을 μ“°λ‹ˆκΉŒ μ΅œμ†Œ 이동 횟수λ₯Ό ꡬ할 μˆ˜κ°€ μ—†μ—ˆλ‹€. μ½”λ“œμ—μ„œ μ•„λž˜ μœ„μΉ˜μ— print문을 μΆ”κ°€ν•˜κ³  이동 νšŸμˆ˜κ°€ μ–΄λ–»κ²Œ 좜λ ₯λ˜λŠ”μ§€ 확인해봀닀.

 

 

 

μ‹œμž‘ μ’Œν‘œλ₯Ό (0, 0) / λͺ©ν‘œ μ’Œν‘œλ₯Ό (7, 0)으둜 μ£Όκ³  μ½”λ“œλ₯Ό 돌린 ν›„ μˆœμ„œλŒ€λ‘œ 좜λ ₯된 μ„Έ 쀄이닀. 두 번째 쀄을 보면 (0, 0)μ—μ„œ (2, 1)은 λ‚˜μ΄νŠΈμ˜ μ›€μ§μž„ νŠΉμ„±μƒ ν•œ 번 λ§Œμ— 갈 수 μžˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  이동 νšŸμˆ˜λŠ” 2번으둜 λ‚˜μ˜€κ³  μžˆλ‹€. μ„Έ 번째 κ²½μš°λ„ λ§ˆμ°¬κ°€μ§€!

 

좜발점 μ’Œν‘œλ₯Ό (x, y)라고 ν•  λ•Œ (x+dx[i], y+dy[i])κΉŒμ§€μ˜ μ΅œμ†Œ 이동 νšŸμˆ˜λŠ” 맨 처음 좜발 μ’Œν‘œμ—μ„œλΆ€ν„° λˆ„μ μœΌλ‘œ κ΅¬ν•˜λŠ” 게 μ•„λ‹ˆλΌ (x, y)λ₯Ό κΈ°μ€€μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 과정이 ν•„μš”ν•΄λ³΄μΈλ‹€.

 

βœ… visited 리슀트 ν™œμš©

첫 번째 μ‹œλ„μ—μ„œ νŒŒμ•…ν•œ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ visited 리슀트의 ν˜•μ‹μ„ 살짝 λ³€ν˜•ν–ˆλ‹€. 2차원 리슀트 ν˜•μ‹μΈ 건 λ™μΌν•˜μ§€λ§Œ λͺ¨λ“  값을 0으둜 μ΄ˆκΈ°ν™”ν•˜κ³  iν–‰ jμ—΄μ—λŠ” μ‹œμž‘μ μ—μ„œ iν–‰ jμ—΄κΉŒμ§€ 였기 μœ„ν•΄ ν•„μš”ν•œ μ΅œμ†Œ 이동 횟수λ₯Ό μ €μž₯ν•΄μ£ΌλŠ” 것이닀.

 

이 λ•Œ μ‹œμž‘μ μ—μ„œ μ‹œμž‘μ κΉŒμ§€λŠ” 이동할 ν•„μš”κ°€ μ—†μ§€λ§Œ κ΅¬ν˜„ 편의λ₯Ό μœ„ν•΄ visited[μ‹œμž‘μ  x μ’Œν‘œ][μ‹œμž‘μ  y μ’Œν‘œ] 값은 1둜 μ΄ˆκΈ°ν™”ν–ˆλ‹€.

 

이 방식을 μ΄μš©ν•œλ‹€λ©΄ (x, y)μ—μ„œ (x+dx[i], y+dy[i])κΉŒμ§€ 였기 μœ„ν•œ μ΅œμ†Œ 이동 νšŸμˆ˜λŠ” visited[x+dx[i]][y+dy[i]] = visited[x][y]+1둜 ν‘œν˜„ν•  수 μžˆλ‹€.

 

β‘’ μ •λ‹΅ 좜λ ₯

좜발점의 초기 값이 1μ΄μ—ˆκΈ° λ•Œλ¬Έμ— 정닡을 ꡬ할 λ•ŒλŠ” visited[νƒ€κ²Ÿ x μ’Œν‘œ][νƒ€κ²Ÿ y μ’Œν‘œ]-1둜 κ³„μ‚°ν•΄μ€˜μ•Ό ν•œλ‹€.

 

3) κ΅¬ν˜„

from collections import deque

T = int(input())

for _ in range(T):
    L = int(input())
    
    s_x, s_y = map(int, input().split())
    t_x, t_y = map(int, input().split())
    
    queue = deque([(s_x, s_y)])
    
    visited = [[0]*(L+1) for _ in range(L+1)]
    
    visited[s_x][s_y] = 1
    
    dx = [-2, -2, -1, -1, 1, 1, 2, 2]
    dy = [-1, 1, -2, 2, -2, 2, -1, 1]
    
    while queue:
        r, c = queue.popleft()
        
        if r == t_x and c == t_y:
            break
        
        for i in range(8):
            nr, nc = r+dx[i], c+dy[i]
            
            if (0 <= nr < L and 0 <= nc < L) and not visited[nr][nc]:
                visited[nr][nc] = visited[r][c]+1
                
                queue.append((nr, nc))

    print(visited[t_x][t_y]-1)

 

4) μ–΄λ €μ› λ˜ 점/배운 μ 

🚨 μ–΄λ €μ› λ˜ 점

  • μ²˜μŒμ— 이동 횟수λ₯Ό 카운트 ν•˜λŠ” λΆ€λΆ„μ—μ„œ 쑰금 헛닀리 짚긴 ν–ˆμ§€λ§Œ 금방 μˆ˜μ •ν–ˆκ³  κ·Έ 외에 μ–΄λ €μš΄ 점은 μ—†μ—ˆλ‹€.

❗ 배운 점

  • μ˜€λŠ˜μ€ 배운 점이라기보닀 κ·Έλƒ₯ λ‚΄ 생각 정리? - λ‹€λ₯Έ μœ ν˜•μ˜ λ¬Έμ œλ³΄λ‹€ BFS/DFS 문제 TIL을 μž‘μ„±ν•  λ•Œ λ‚΄κ°€ μ΄ν•΄ν•œ 게 λ§žλ‚˜? μ΄λ ‡κ²Œ ν‘œν˜„ν•˜λ©΄ λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ 잘 μ•Œμ•„ 듀을 수 μžˆμ„κΉŒ? ν•˜λŠ” 생각이 μœ λ… 많이 λ“ λ‹€. 문제λ₯Ό 많이 풀어보고, 풀이λ₯Ό 많이 μ μ–΄λ³΄λŠ” 방법 λ°–μ—λŠ” 없겠지 πŸ”₯