220v
젝무의 개발새발
220v
전체 방문자
오늘
어제
  • 분류 전체보기 (255)
    • AI (35)
      • ML, DL 학습 (30)
      • 논문 리뷰 (4)
      • 실습 및 프로젝트 (1)
    • Algorithm (145)
      • LeetCode (13)
      • 프로그래머스 (35)
      • 백준 (96)
      • 알고리즘, 문법 정리 (1)
    • Mobile, Application (17)
      • Flutter (10)
      • iOS, MacOS (7)
    • BackEnd (7)
      • Flask (1)
      • Node.js (5)
      • Spring, JSP..etc (1)
    • Web - FrontEnd (18)
      • JavaScript, JQuery, HTML, C.. (12)
      • React (6)
    • DataBase (1)
      • MySQL (1)
      • Firebase Firestore (0)
      • Supabase (0)
    • Git (1)
    • 기타 툴 및 오류 해결 (3)
    • 강의 (5)
      • Database (3)
      • 암호학 (2)
      • 알고리즘 (0)
    • 후기와 회고 (2)
    • 블로그 꾸미기 (1)
    • 일상과 이것저것 (20)
      • 맛집 (12)
      • 세상사는일 (4)
      • 도서리뷰 (1)
      • 이런저런 생각들 (잡글) (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • implementation
  • 백준
  • top-down
  • BFS
  • Dynamic Programming
  • REACT
  • Mathematics
  • brute-Force
  • dfs
  • Prefix Sum
  • simulation
  • bitmasking
  • 티스토리챌린지
  • Priority Queue
  • 구현
  • Lis
  • two pointer
  • dp
  • 다익스트라
  • disjoint set
  • 프로그래머스
  • IMPLEMENT
  • union-find
  • Greedy
  • binary search
  • topological sort
  • Backtracking
  • Minimum Spanning Tree
  • 오블완
  • 위상 정렬

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
220v

젝무의 개발새발

Algorithm/백준

[백준] 16724. 피리 부는 사나이 - Python

2023. 11. 6. 03:08

[Gold III]

 

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

 

16724번: 피리 부는 사나이

첫 번째 줄에 지도의 행의 수를 나타내는 N(1 ≤ N ≤ 1,000)과 지도의 열의 수를 나타내는 M(1 ≤ M ≤ 1,000)이 주어진다. 두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열이 주

www.acmicpc.net

 

풀이

Union-Find(Disjoint Set)를 이용하여 풀 수 있는 문제라는 것만 캐치한다면, 어렵지 않게 풀이할 수 있었던 문제.

 

NxM 지도의 각 칸에 번호를 지정하고, (좌표가 r, c 일 때, 칸의 번호를 r * M + c 로 지정.)

그 번호를 기반으로 root를 저장하는 dictionary를 초기화.

 

Union, Find 함수를 구현한 후엔,

지도의 모든 칸을 순회하며, 그 칸의 진행 방향(R, L, U, D)에 따라, 다음 칸과 union해 준다. (line 43~45)

 

그 이후에는, 접근할 수 있는 칸들끼리는 Union이 되어 있는 상태이다.

따라서, 모든 칸에 대해 다시 순회하며, 동일한 root를 가진 칸은 제외, 서로 다른 root를 가진 칸의 집합의 개수를 센다.

결국, Disjoint Set의 개수를 세면 된다.

그렇다면, 그 Disjoint Set들의 root인 칸에 Safe Zone을 만들면 문제가 해결된다.

 

** EX. (예제 입력 1)

예제 입력 1의 모든 칸에 번호를 매기면 아래와 같다.

0  1  2  3
4  5  6  7
8  9  10 11

이후, 모든 칸을 순회하며 union을 진행한 후엔, 모든 칸의 root의 번호 (find(x)의 결과)는 다음과 같다.

0  0  0  0
0  5  5  0
0  0  0  0

따라서, root가 0인 Set과 root가 5인 Set. 2개로 묶였으므로, 각 Set의 어디에든 Safe Zone을 하나씩 설치하면 된다.

 

AC.

N, M = map(int, input().split())

g = []
for _ in range(N):
    g.append(list(input()))
    
# 좌표가 [r][c]일 때, 임의로 칸의 번호를 `r * M + c` 로 지정.
root = {i: i for i in range(N*M)}

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

def union(x, y):
    rx = find(x)
    ry = find(y)
    if rx < ry:
        root[ry] = rx
    else:
        root[rx] = ry

def go(r, c):
    nowIndex = r*M+c
    if g[r][c] == "R":
        if c == M-1:
            return
        union(nowIndex, nowIndex+1)
    elif g[r][c] == "L":
        if c == 0:
            return
        union(nowIndex, nowIndex-1)
    elif g[r][c] == "U":
        if r == 0:
            return
        union(nowIndex, nowIndex-M)
    elif g[r][c] == "D":
        if r == N-1:
            return
        union(nowIndex, nowIndex+M)

for r in range(N):
    for c in range(M):
        go(r, c)

result = {}
for r in range(N):
    for c in range(M):
        nowIndex = r*M+c
        result[find(nowIndex)] = 1

print(len(result))

 

    'Algorithm/백준' 카테고리의 다른 글
    • [백준] 1948. 임계경로 - Python
    • [백준] 3584. 가장 가까운 공통 조상 - Python
    • [백준] 13164. 행복 유치원 - Python
    • [백준] 17089. 세 친구 - Python
    220v
    220v
    DGU CSE 20 / Apple Developer Academy @ POSTECH 2nd Jr.Learner.

    티스토리툴바