[Python] [BOJ] 피리 부는 사나이(16724)

긍정왕·2021년 7월 18일
1

Algorithm

목록 보기
52/69
post-thumbnail

💡 문제 해결

  1. 모든 칸을 순회하며 이동할 칸에 대한 정보를 갱신
  2. 만약 이동할 칸이 board의 범위를 벗어나지 않는다면 부모노드를 갱신
  3. 모든 칸의 순회를 마친 뒤 부모노드의 개수가 연결된 경로의 개수이자 필요한 safe_zone의 개수

📌 값 칸에 대한 고유값을 어떻게 지정할지 생각해내는데 애먹었던 문제



🧾 문제 설명

피리 부는 사나이 성우는 오늘도 피리를 분다.

성우가 피리를 불 때면 영과일 회원들은 자기도 모르게 성우가 정해놓은 방향대로 움직이기 시작한다. 
성우가 정해놓은 방향은 총 4가지로 U, D, L, R이고 각각 위, 아래, 왼쪽, 오른쪽으로 이동하게 한다.

이를 지켜보던 재훈이는 더 이상 움직이기 힘들어하는 영과일 회원들을 지키기 위해 
특정 지점에 ‘SAFE ZONE’ 이라는 최첨단 방음 시설을 만들어 회원들이 성우의 피리 소리를 듣지 못하게 하려고 한다. 
하지만 예산이 넉넉하지 않은 재훈이는 성우가 설정해 놓은 방향을 분석해서 최소 개수의 ‘SAFE ZONE’을 만들려 한다. 

성우가 설정한 방향 지도가 주어졌을 때 재훈이를 도와서 영과일 회원들이 지도 어느 구역에 있더라도 
성우가 피리를 불 때 ‘SAFE ZONE’에 들어갈 수 있게 하는 ‘SAFE ZONE’의 최소 개수를 출력하는 프로그램을 작성하시오.

문제보기



🖨 입출력



📝 풀이

import sys


input = sys.stdin.readline
move = {
    'L': (0, -1),
    'R': (0, 1),
    'U': (-1, 0),
    'D': (1, 0),
}

def find(x):
    if parent[x] == x: return x

    parent[x] = find(parent[x])
    return parent[x]


def union(x, y):
    x, y = find(x), find(y)

    if x == y: return False

    if rank[x] < rank[y]:
        x, y = y, x

    parent[y] = x

    if rank[x] == rank[y]:
        rank[x] += 1
    return True



N, M = map(int, input().split())
board = list(input().rstrip('\n') for _ in range(N))

parent = [i for i in range(N * M)]
rank = [1] * (N * M)

for idx in range(N * M):
    x, y = idx // M, idx % M
    dx, dy = move.get(board[x][y])
    nx, ny = x + dx, y + dy
    if 0 <= nx * M + ny < N * M:
        union(idx, nx * M + ny)

answer = len(set(find(val) for val in range(N * M)))
print(answer)

profile
Impossible + 땀 한방울 == I'm possible

0개의 댓글