BOJ

[골드 2] 16946번: 벽 부수고 이동하기 4

2022. 9. 25. 12:02
목차
  1. 문제
  2. 입력
  3. 출력
  4. 풀이
  5. 내가 작성한 소스코드
  6. 남이 작성한 소스코드
  7. 피드백
728x90

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

 

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

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

www.acmicpc.net


문제

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

각각의 벽에 대해서 다음을 구해보려고 한다.

  • 벽을 부수고 이동할 수 있는 곳으로 변경한다.
  • 그 위치에서 이동할 수 있는 칸의 개수를 세어본다.

한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다.

출력

맵의 형태로 정답을 출력한다. 원래 빈 칸인 곳은 0을 출력하고, 벽인 곳은 이동할 수 있는 칸의 개수를 10으로 나눈 나머지를 출력한다.


풀이

Naive하게 '모든 칸을 순회하면서 벽이 나오면 BFS를 돌리자' 라고 생각하면 시간 초과가 뜬다. 적어도 Python으로는 그렇다. 다른 방법으로 접근해야 한다.

우선 미로를 순회하면서 빈 칸을 먼저 찾는다. 빈 칸이 나오면 BFS를 돌려서 해당 칸이 속한 빈 영역을 찾아 표시한다. 정수형 사전 자료형을 사용해 영역을 {key : area} 형태로 저장하고, 표시할 때는 미로와 같은 크기의 2차원 List에 Key값을 표시하면 된다. 모든 칸을 순회했으면 이제 벽을 찾아서 해당 벽의 상하좌우에 있는 빈 영역의 넓이를 다 더해준다. 이때 같은 영역의 넓이를 중복해서 더하지 않도록 주의한다.

내가 작성한 소스코드

# Pypy3로 제출

import sys
from collections import deque
r = sys.stdin.readline


def bfs(board, target_board, num, start_pos, d, size):
    y = start_pos[0]; x = start_pos[1]
    n = size[0]; m = size[1]
    blanks_cnt = 0

    q = deque()
    q.append((y, x))
    target_board[y][x] = num
    blanks_cnt += 1
    
    while q:
        (y, x) = q.popleft()

        for (dy, dx) in d:
            ny = y + dy
            nx = x + dx

            if (ny < 0 or ny > n-1) or (nx < 0 or nx > m-1):
                continue

            if target_board[ny][nx] > 0 or board[ny][nx] == 1:
                continue

            q.append((ny, nx))
            target_board[ny][nx] = num
            blanks_cnt += 1
    
    return blanks_cnt

def get_blanks(board, blank_dict, pos, d, size):
    y = pos[0]; x = pos[1]
    n = size[0]; m = size[1]
    blanks_cnt = 1
    blanks_to_add = set()

    for (dy, dx) in d:
        ny = y + dy
        nx = x + dx

        if (ny < 0 or ny > n-1) or (nx < 0 or nx > m-1) or board[ny][nx] < 0:
            continue

        blanks_to_add.add(board[ny][nx])

    for v in blanks_to_add:
        blanks_cnt += blank_dict[v]

    return blanks_cnt % 10


n, m = map(int, r().split())
maze = []
for _ in range(n):
    maze.append(list(map(int, r().rstrip())))
blanks = dict(); blank_key = 0
maze_blanks = [[-1] * m for _ in range(n)]
d = ((-1, 0), (0, -1), (1, 0), (0, 1))

for i in range(n):
    for j in range(m):
        if maze[i][j] == 0 and maze_blanks[i][j] == -1:
            blank_key += 1
            blanks[blank_key] = bfs(maze, maze_blanks, blank_key, (i, j), d, (n, m))

for i in range(n):
    for j in range(m):
        if maze[i][j] == 1:
            maze[i][j] = get_blanks(maze_blanks, blanks, (i, j), d, (n, m))

for row in maze:
    print("".join(map(str, row)))

남이 작성한 소스코드

koosaga 님:
https://www.acmicpc.net/source/12130779

피드백

  • C++을 배워서 Python으로 풀었을 때 시간 초과가 날 것 같은 문제들은 C++로 풀자. 분명 Logic은 맞는데 시간 초과 때문에 틀리면 억울하다.
  • 긴 조건문을 반복해서 사용할 때는 조건문을 함수화해서 코드의 가독성을 높일 수 있다.
저작자표시 (새창열림)

'BOJ' 카테고리의 다른 글

[골드 3] 6087번: 레이저 통신  (0) 2022.10.05
[골드 3] 14442번: 벽 부수고 이동하기 2  (0) 2022.09.27
[골드 3] 2206번: 벽 부수고 이동하기  (1) 2022.09.24
[실버 3] 15656번: N과 M (7)  (0) 2022.09.22
[실버 5] 1476번: 날짜 계산  (0) 2022.09.21
  • 문제
  • 입력
  • 출력
  • 풀이
  • 내가 작성한 소스코드
  • 남이 작성한 소스코드
  • 피드백
'BOJ' 카테고리의 다른 글
  • [골드 3] 6087번: 레이저 통신
  • [골드 3] 14442번: 벽 부수고 이동하기 2
  • [골드 3] 2206번: 벽 부수고 이동하기
  • [실버 3] 15656번: N과 M (7)
Park Joonyoung
Park Joonyoung
개발 블로그
DevJoon개발 블로그
Park Joonyoung
DevJoon
Park Joonyoung
전체
오늘
어제
  • 분류 전체보기 (88)
    • BOJ (41)
      • 틀렸습니다 (6)
    • 알고리즘 (4)
    • C++ (2)
    • Python (1)
    • 토이 프로젝트 (0)
    • 선형대수학 (1)
    • 기타 (3)
    • 에세이 (4)
    • [개인 보관용] (32)
      • 이코테 강의 정리 (0)
      • 알고리즘(old) (0)
      • 단변수미적분학 (0)
      • 다변수미적분학 (0)
      • 선형대수학 (32)
      • 선형대수학(old) (0)
      • 프랑스어 (0)
      • 독서노트 (0)
      • 사진 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Python
  • It
  • DP
  • 시뮬레이션
  • ps
  • 알고리즘
  • DevJoon
  • 백트래킹
  • 에세이
  • 구현
  • 백준
  • 코딩테스트
  • bfs
  • c++
  • Notion
  • dfs
  • next_permutation
  • 개발
  • github
  • git bash
  • BOJ
  • 그리디
  • 선형대수학
  • 수학
  • stl
  • 브루트포스

최근 댓글

최근 글

hELLO · Designed By 정상우.
Park Joonyoung
[골드 2] 16946번: 벽 부수고 이동하기 4
상단으로

티스토리툴바

단축키

내 블로그

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

블로그 게시글

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

모든 영역

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

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