Home 백준 - 2206 벽 부수고 이동하기 풀이
Post
Cancel

백준 - 2206 벽 부수고 이동하기 풀이

문제

2206 벽 부수고 이동하기

screencapture

풀이

1. 알고 있어야 할 점

  • 이 문제는 너비 우선 탐색(bfs)을 이용하여 푸는 문제이다.
  • 가중치가 모두 동일한 최단거리 문제는 대부분 너비 우선 탐색으로 풀 수 있다.
    • 가중치가 있는 경우 다익스트라 알고리즘 등으로 풀 수 있다.
  • 일반적인 너비 우선 탐색 문제와 차이는 벽을 1번 부술 수 있다는 점이다.

Step by Step

1. 초기화

  • 입력된 맵을 배열로 선언한다.
  • 큐를 생성하고, 시작 노드의 정보를 입력한다.
    • 들어가야 할 정보는 노드의 좌표, 현재까지 지나온 거리, 벽을 부수었는지 여부 이다.
  • 각 경로의 방문 여부(지나 왔는지 여부) 저장할 공간을 선언한다.
    • 방문 여부는 벽을 부수고 방문과 벽을 부수지 않고 방문하였는지를 각각 저장한다.

2. BFS 수행

  • 큐에 값이 있으면 계속 수행되는 반복문을 선언한다.
  • 큐에서 노드를 하나 꺼낸다.
  • 해당 노드의 좌표가 맵의 마지막(목적지)이면 노드의 거리를 출력하고 프로그램을 종료한다.
  • 해당 노드의 좌표가 맵의 범위를 벗어났으면 2를 처음부터 반복한다.
  • 해당 노드가 이미 벽을 부수었고, 현재 위치가 벽이면 2를 처음부터 반복한다.
  • 해당 노드가 이미 방문 한 곳인지 확인하고, 방문한 곳이면 2를 처음부터 반복한다.
  • 해당 노드의 상하좌우 인접한 노드를 큐에 저장한다.
    • 해당 노드가 이미 벽을 부수었더나, 현재 위치가 벽이면 벽을 부수었다고 표시한다.

3. 종료

  • 2에서 큐가 비어서 반복문이 종료되었다면 -1을 출력하고 프로그램을 종료한다.

kotlin code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
fun main() {
    val map: Array<BooleanArray> = readMap()
    val shortestDistance: Int = getShortestDistance(map)
    println(shortestDistance)
}

private fun readMap(): Array<BooleanArray> = Array(readln().split(' ').first().toInt()) { readln().toCharArray().map { it == '1' }.toBooleanArray() }

private fun getShortestDistance(map: Array<BooleanArray>): Int {
    val queue: java.util.Queue<Node> = java.util.LinkedList<Node>().apply {
        this.offer(Node(0, 0, 1, false))
    }
    val xDirection = arrayOf(1, -1, 0, 0)
    val yDirection = arrayOf(0, 0, 1, -1)

    val visited = Array(2) { Array(map.size) { BooleanArray(map.first().size) { false } } }

    while (queue.isNotEmpty()) {
        val node = queue.poll()
        if(node.isEndOfMap(map)) return node.distance
        
        if(node.isOutOfRangeOfMap(map)) continue
        if(node.isDuplicateBreak(map)) continue
        if(node.isDuplicateVisit(visited)) continue

        visited[node.didBreakWall.toInt()][node.y][node.x] = true

        for(i in 0..3)
            queue.offer(node.getNext(xDirection[i], yDirection[i], map))
    }
    return -1
}

data class Node(val x: Int, val y: Int, val distance: Int, val didBreakWall: Boolean) {
    fun getNext(xDirection: Int, yDirection: Int, map: Array<BooleanArray>) = Node(x + xDirection, y + yDirection,distance + 1, didBreakWall || map[y][x])
    fun isOutOfRangeOfMap(map: Array<BooleanArray>) = x !in (0..map.first().lastIndex) || y !in (0..map.lastIndex)
    fun isEndOfMap(map: Array<BooleanArray>) = x == map.first().lastIndex && y == map.lastIndex
    fun isDuplicateBreak(map: Array<BooleanArray>) = didBreakWall && map[y][x]
    fun isDuplicateVisit(visited: Array<Array<BooleanArray>>) = visited[didBreakWall.toInt()][y][x]
}

private fun Boolean.toInt() = if(this) 1 else 0
This post is licensed under CC BY 4.0 by the author.

백준 - 1753 최단경로 풀이

도메인 주도 설계 첫걸음 - 책 소개