본문 바로가기
코딩테스트 파이썬/백준

피리 부는 사나이 ( 16724 번 )

by 세용용용용 2025. 9. 7.

16724번: 피리 부는 사나이

 


🧠 알고리즘

  • 사이클 탐지 + 경로 압축 (Cycle Detection with Path Compression)

 

✔️ 동작 방식

  • 아직 방문되지 않은 방향 칸을 시작점으로 탐색 시작.
  • 현재 칸에서 지정된 방향으로 계속 이동하면서 visit_set에 경로를 저장.
  • 이미 처리된 영역으로 도달: 지금까지의 경로 칸들을 같은 번호로 갱신.
  • 자기 자신으로 다시 돌아옴 (사이클 발견): 경로 전체에 새로운 num을 부여.
  • 최종 모든 사이클의 개수(num) 반환.

 

 

🧾 코드

import sys

def _main(n, m):
    map_list = [list(sys.stdin.readline().rstrip()) for _ in range(n)]
    num = 0
    move_dict = {'U': (-1, 0), 'D': (1, 0), 
                 'L': (0, -1), 'R': (0, 1)}
    
    for i in range(n):
        for j in range(m):
            if map_list[i][j] in ('U', 'D', 'L', 'R'):
                x, y = i, j
                visit_set = {(i, j)}
                count = 0

                while True:
                    move_x, move_y = move_dict[map_list[x][y]]
                    next_x, next_y = x + move_x, y + move_y

                    if map_list[next_x][next_y] not in ('U', 'D', 'L', 'R'): # 이미 길이 개척된 경우
                        for go_x, go_y in visit_set:
                            map_list[go_x][go_y] = map_list[next_x][next_y]
                        break
                        
                    if (next_x, next_y) not in visit_set:
                        visit_set.add((next_x, next_y))
                        x, y = next_x, next_y
                    else:
                        for go_x, go_y in visit_set:
                            map_list[go_x][go_y] = num
                        num += 1
                        break

    return num

n, m = map(int, sys.stdin.readline().rstrip().split())
print(_main(n, m))

 

 

⏱️ 시간 복잡도

for i in range(n) : 이차형 리스트를 탐색하며 경로 압축 ( 이차형 시간 복잡도 )
    for j in range(m)
    
이미 처리된 경우는 상수 시간으로 바로 종료
해당 알고리즘 시간 복잡도 : 이차형 시간 복잡도 ( O(n ** 2) )

'코딩테스트 파이썬 > 백준' 카테고리의 다른 글

보석 도둑 ( 1202 번 )  (0) 2025.09.08
노드사이의 거리 ( 1240 번 )  (0) 2025.09.08
벽 부수고 이동하기 4 ( 16946 번 )  (0) 2025.09.06
단어 만들기 ( 1148 번 )  (0) 2025.09.06
배 ( 1092 번 )  (0) 2025.09.02