문제
로봇 청소기와 방의 상태가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.
로봇 청소기가 있는 방은 N X M 크기의 직사각형으로 나타낼 수 있으며, 1×1 크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북 중 하나이다. 방의 각 칸은 좌표 ( 로 나타낼 수 있고, 가장 북쪽 줄의 가장 서쪽 칸의 좌표가 (0,0) 가장 남쪽 줄의 가장 동쪽 칸의 좌표가 ( 이다. 즉, 좌표 는 북쪽에서 번째에 있는 줄의 서쪽에서 번째 칸을 가리킨다. 처음에 빈 칸은 전부 청소되지 않은 상태이다.
로봇 청소기는 다음과 같이 작동한다.
- 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
- 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
- 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
- 반시계 방향으로 90도 회전한다.
- 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
- 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 |