알고리즘 (PS)/BOJ

[백준] 16946 - 벽 부수고 이동하기 4 (G2)

2021. 12. 1. 15:21
반응형

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

 

16946번: 벽 부수고 이동하기 4

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이

www.acmicpc.net

이 문제는 그래프 탐색 문제를 조금 꼬아낸 문제이다.

제일 나이브한 풀이는 각 벽에 대해 BFS를 수행하는 것인데, 아무리 봐도 이건 시간 초과 풀이이다.

전체 영역이 최대 100만 칸짜리 2차원 배열인데, 이를 중복해서 순회하면 시간 초과가 안날 수 없다.

 

2차원배열을 한번만 순회하여, 그 결과를 이용해 답을 도출해야 한다.

그래서 나는 비어있는 영역에 대해 BFS를 수행하여 넓이를 미리 구해놓고,

벽에 대해 상하좌우를 확인하여 빈공간이 있을 경우, 해당 빈 공간이 속해있는 영역 사이즈를 더해주도록 했다.

 

이때 주의 할 점은

00

01

이렇게 그래프가 있다고 한다면, 벽의 왼쪽 빈공간과, 벽의 위쪽 빈공간이 같은 영역에 속해 있기 때문에

중복해서 세지 않도록 각 빈공간이 속한 '영역(그룹)'을 잘 구분해줘야 한다.

 

이걸 이제 어떻게 구현하느냐는 사람마다 다르겠지만, 나는 분리집합 아이디어를 살짝 차용했다.

(실제 분리집합을 구현하진 않았다.)

 

위 예시에서

00

01

분리집합의 대표 원소로 '빈공간의 좌표'를 설정했다.

그러면 초기 분리집합의 데이터는 아래와 같이 들어있었을 것이다.

(1, 1)은 빈공간이 아니니 사실상 무시된다.

(0, 0) (0, 1)

(1, 0) (1, 1)

 

그리고 (0, 0)에 대해 BFS를 수행하고, 이 과정에서 방문한 모든 정점의 부모를 (0, 0)으로 넣어준다.

(0, 0) (0, 0)

(0, 0) (1, 1)

 

그리고 BFS를 수행하면서 정점을 방문할 때마다 이 그룹의 영역 넓이를 1씩 증가시켜준다.

그럼 (0, 0) 이라는 그룹의 영역 넓이는 3이되고

(0, 1) (1, 0) 이 속한 영역의 넓이를 구하기 위해 (0, 0)의 영역의 넓이를 구하게끔 하면 된다.

 

이때 중복된 영역의 넓이를 더해주지 않도록 하기 위해 'Set' 자료구조를 활용하여

한번 방문한 영역 그룹은 중복하여 방문하지 않게 하면 답을 구할 수 있다.

 

import sys
from collections import deque
input = sys.stdin.readline
TEST_MODE = False
dx = di = [1, -1, 0, 0]
dy = dj = [0, 0, 1, -1]


def print_board(board, n, desc=""):
    if desc:
        print(desc)
    for i in range(n):
        print(*board[i])
    print()


def solve():
    # input
    n, m = map(int, input().split())
    board = [list(map(int, list(input().rstrip()))) for _ in range(n)]
    if TEST_MODE:
        print_board(board, n)

    # BFS Settings
    visit = [[False for _ in range(m)] for _ in range(n)]
    parent = [[(i, j) for j in range(m)] for i in range(n)]
    area_at = [[0 for _ in range(m)] for _ in range(n)]
    d = deque()

    # board 내 각각의 빈 공간에 대해서 BFS 수행하여 넓이 구하기
    for i in range(n):
        for j in range(m):
            if board[i][j] == 0 and not visit[i][j]:
                d.append((i, j))
                visit[i][j] = True
                area = 1
                while d:
                    now_i, now_j = d.popleft()
                    for k in range(4):
                        check_i, check_j = now_i + di[k], now_j + dj[k]
                        if 0 <= check_i < n and 0 <= check_j < m:
                            if not visit[check_i][check_j] and board[check_i][check_j] == 0:
                                parent[check_i][check_j] = (i, j)
                                visit[check_i][check_j] = True
                                d.append((check_i, check_j))
                                area += 1
                area_at[i][j] = area
    if TEST_MODE:
        print_board(parent, n, "parent")
        print_board(visit, n, "visit")
        print_board(area_at, n, "area_at")

    # answer count
    for i in range(n):
        for j in range(m):
            if board[i][j] == 1:
                s = set()
                for k in range(4):
                    check_i = i + di[k]
                    check_j = j + dj[k]
                    if 0 <= check_i < n and 0 <= check_j < m and board[check_i][check_j] == 0:
                        area_pos = parent[check_i][check_j]
                        if area_pos not in s:
                            s.add(area_pos)
                            board[i][j] += area_at[area_pos[0]][area_pos[1]]
                            board[i][j] %= 10

    # print answer
    for i in range(n):
        for j in range(m):
            print(board[i][j], end='')
        print()


if __name__ == '__main__':
    solve()
반응형
저작자표시 비영리 변경금지 (새창열림)

'알고리즘 (PS) > BOJ' 카테고리의 다른 글

[백준] 13460 - 구슬 탈출 2 (G1)  (0) 2021.12.04
[백준] 2565 - 전깃줄 (S1)  (0) 2021.12.01
[백준] 12100 - 2048 (Easy) (G2)  (0) 2021.11.24
[백준] 2473 - 세 용액 (G4)  (0) 2021.11.21
[백준] 17070 - 파이프 옮기기 1 (G5)  (0) 2021.11.14
'알고리즘 (PS)/BOJ' 카테고리의 다른 글
  • [백준] 13460 - 구슬 탈출 2 (G1)
  • [백준] 2565 - 전깃줄 (S1)
  • [백준] 12100 - 2048 (Easy) (G2)
  • [백준] 2473 - 세 용액 (G4)
에버듀
에버듀
개발은 좋은데 뭘로 개발할까
에버듀
Blog. 에버듀
에버듀
전체
오늘
어제
  • 분류 전체보기 (606)
    • 개인 프로젝트 (43)
      • [2020] 카카오톡 봇 (9)
      • [2021] 코드악보 공유APP (22)
      • [2022] 유튜브 뮤직 클론코딩 (9)
      • [2025] 고성능 에코서버 만들기 (0)
      • 간단한 프로젝트 (3)
    • 팀 프로젝트 (22)
      • [2020] 인공지능 숫자야구 (4)
      • [2022] OSAM 온라인 해커톤 (10)
      • [2024] GDSC 프로젝트 트랙 (6)
      • [2025] 큰소리 웹 페이지 (2)
    • 알고리즘 (PS) (107)
      • BOJ (101)
      • Programmers (5)
      • 알고리즘 이모저모 (1)
    • CS (329)
      • 자료구조 (19)
      • 어셈블리 (41)
      • 멀티미디어응용수학 (7)
      • 컴퓨터 구조 (29)
      • 알고리즘 분석 (4)
      • 컴퓨터 네트워크 (38)
      • 프로그래밍언어론 (15)
      • HCI 윈도우즈프로그래밍 (26)
      • 기초데이터베이스 (29)
      • 운영체제 (23)
      • 오토마타 (24)
      • 문제해결기법 (11)
      • 블록체인 (22)
      • 소프트웨어공학 (21)
      • 기계학습심화 (12)
      • 컴퓨터그래픽스와 메타버스 (8)
    • 자기계발 (37)
      • 동아리 (7)
      • 자격증 (3)
      • 코딩테스트, 대회 (8)
      • 생각 정리 (18)
      • 머니 스터디 (1)
    • WEB(BE) (5)
      • express.js (1)
      • flask (0)
      • Spring & Spring Boot (4)
    • WEB(FE) (2)
      • html, css, js (1)
      • React.js (1)
    • Tool & Language (6)
      • Edit Plus (1)
      • Git (1)
      • Python3 (2)
      • Java (2)
    • Infra (12)
      • AWS (1)
      • Oracle Cloud (8)
      • Firebase (2)
      • Network (1)
    • Android (18)
      • Java (6)
      • Flutter (12)
    • Window (2)
      • Visual Studio 없이 WPF (1)
      • MFC (1)
    • 독서 (14)
      • Inside Javascript (7)
      • Database Internals (6)
      • 한 글 후기 (1)
    • 인턴 (8)
      • 델파이 (7)
      • Oracle (1)

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.1.4
에버듀
[백준] 16946 - 벽 부수고 이동하기 4 (G2)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.