문제

로봇 청소기와 방의 상태가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.

로봇 청소기가 있는 방은 N X M 크기의 직사각형으로 나타낼 수 있으며, 1×1 크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북 중 하나이다. 방의 각 칸은 좌표 (로 나타낼 수 있고, 가장 북쪽 줄의 가장 서쪽 칸의 좌표가 (0,0) 가장 남쪽 줄의 가장 동쪽 칸의 좌표가 (이다. 즉, 좌표 는 북쪽에서 번째에 있는 줄의 서쪽에서 번째 칸을 가리킨다. 처음에 빈 칸은 전부 청소되지 않은 상태이다.

로봇 청소기는 다음과 같이 작동한다.

  1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
  2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
    1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
    2. 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
  3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
    1. 반시계 방향으로 90도 회전한다.
    2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
    3. 1번으로 돌아간다.

입력

첫째 줄에 방의 크기 이 입력된다. (3≤N,M≤50)  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 와 처음에 로봇 청소기가 바라보는 방향 d가 입력된다.d가 0인 경우 북쪽, 1인 경우 동쪽, 2인 경우 남쪽, 3인 경우 서쪽을 바라보고 있는 것이다.

셋째 줄부터 개의 줄에 각 장소의 상태를 나타내는 N X M개의 값이 한 줄에 개씩 입력된다. 번째 줄의 번째 값은 칸 의 상태를 나타내며, 이 값이 0인 경우가 청소되지 않은 빈 칸이고, 1인 경우 에 벽이 있는 것이다. 방의 가장 북쪽, 가장 남쪽, 가장 서쪽, 가장 동쪽 줄 중 하나 이상에 위치한 모든 칸에는 벽이 있다. 로봇 청소기가 있는 칸은 항상 빈 칸이다.

출력

로봇 청소기가 작동을 시작한 후 작동을 멈출 때까지 청소하는 칸의 개수를 출력한다.

내가 푼 풀이

- 문제는 어렵지않으나 해당 로봇의 작동을 구현하는데 좀 생각이 많아졌다.

- 작동할 수 없을때 까지 최대로 돌려서 청소한 구역의 수를 구하는문제다.

- 해당 로봇의 작동을 함수로 정하고, while을 무한으로 돌려 탈출조건(4구역이 청소되거나 벽인상태에서 후진할수 없는 상태)이 성립하면 나오도록 구현하였다.

 

import Foundation

// 입력받기
let input = readLine()!.split(separator: " ").map{Int(String($0))!}
let N = input[0], M = input[1]
let input2 = readLine()!.split(separator: " ").map{Int(String($0))!}
var robotLoc = (x: input2[0], y: input2[1])
var dir = input2[2]
var room = [[Int]]()
var count = 0
for i in 0..<N {
    room.append(readLine()!.split(separator: " ").map{Int(String($0))!})
}

// 탈출조건이 만족할때 까지 청소
while true {
    if !find(loc: &robotLoc, dir: &dir) {
        break
    }
}
// 청소된 방의 구역수를 세고 출력
for i in 0..<room.count {
    count += room[i].filter{ $0 == -1}.count
}
print(count)

// 구역 청소
func cleaning(loc: (x: Int, y: Int)) {
    if room[loc.x][loc.y] == 0 {
        room[loc.x][loc.y] = -1
    }
}

// 인접한 4개의 구역 확인
func find(loc: inout (x: Int, y: Int), dir: inout Int) -> Bool{
    // 4개 구역 임의의 수입력
    var upp = -2, rightp = -2, downp = -2, leftp = -2
    // 청소할수 없다 (벽이거나 이미 청소된곳)
    var cant = [1,-1]
    // 처음에 주어지는 위치는 청소되지않는곳으로 부여되므로 일단 청소
    cleaning(loc: loc)
    
    // 주어진 위치의 상 하 좌 우 위치를 구한다.
    // 인덱스 범위를 넘어도 벽(1) 로 설정
    if loc.x-1 >= 0 {
        upp = room[loc.x-1][loc.y]
    } else { upp = 1 }
    
    if loc.y+1 < M {
        rightp = room[loc.x][loc.y+1]
    } else { rightp = 1 }
    
    if loc.x+1 < N {
        downp = room[loc.x+1][loc.y]
    } else { downp = 1 }
    
    if loc.y-1 >= 0 {
        leftp = room[loc.x][loc.y-1]
    } else { leftp = 1 }
    
    // 4개 인접한 구역이 청소할 수 없는경우(이미청소됬거나, 벽인 경우)
    if cant.contains(upp) && cant.contains(downp) && cant.contains(leftp) && cant.contains(rightp) {
        // 방향에 따라 후진한다.
        // 후진 할 수 없는경우 로봇의 작동 멈춤
        if dir == 0 {
            if downp == 1 {
                return false
            } else {
                loc.x += 1
                return true
            }
        }
        if dir == 1 {
            if leftp == 1 {
                return false
            } else {
                loc.y -= 1
                return true
            }
        }
        if dir == 2 {
            if upp == 1 {
                return false
            } else {
                loc.x -= 1
                return true
            }
        }
        if dir == 3 {
            if rightp == 1 {
                return false
            } else {
                loc.y += 1
                return true
            }
        }
    } else {
        // 4군데중 청소할 곳이 있는경우
        // 방향에 따라 위치로 이동하고 청소
        dir -= 1
        if dir == -1 {
            dir = 3
        }
        if dir == 0 {
            if upp == 0 {
                loc.x -= 1
                cleaning(loc: loc)
            }
        } else if dir == 1 {
            if rightp == 0 {
                loc.y += 1
                cleaning(loc: loc)
            }
        } else if dir == 2 {
            if downp == 0 {
                loc.x += 1
                cleaning(loc: loc)
            }
        }else {
            if leftp == 0 {
                loc.y -= 1
                cleaning(loc: loc)
            }
        }
        return true
    }
    return true
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-5052 전화번호 목록 Swift  (0) 2024.04.14
BOJ-2470 두 용액 Swift  (0) 2024.04.14
BOJ-1011 Fly me to the Alpha Centauri Swift  (0) 2024.04.13
BOJ-10974 모든 순열 Swift  (0) 2024.04.13
BOJ-15683 감시 Swift  (1) 2024.04.12

+ Recent posts