Algorithm/BOJ
백준 14503 로봇 청소기
삼쓰 웅쓰
2021. 3. 19. 14:04
728x90
출처: www.acmicpc.net/problem/14503
분류: 시뮬레이션
접근방식
현재 방향을 생각하면서 청소기를 돌려주면 되는 문제였습니다.
저는 현재 로봇 청소기의 위치와 현재 방향을 전역변수로 두고 둘을 조작해주면서 계산했습니다.
방향을 enum 타입으로 정의했고
청소기는 계속 왼쪽 방향으로 회전하기 때문에 각 방향에서 왼쪽으로 회전하는 함수를 만들었습니다.
enum Direction: Int {
case up = 0, right, down , left
mutating func turnLeft() {
switch self {
case .up: self = .left
case .left: self = .down
case .down: self = .right
case .right: self = .up
}
}
}
현재 방향과 위치에서 앞 뒤도 계속 사용되기 때문에 computed property로 만들어줬습니다.
var front: Point {
switch currentDir {
case .up: return (currentPoint.r-1, currentPoint.c)
case .left: return (currentPoint.r, currentPoint.c-1)
case .down: return (currentPoint.r+1, currentPoint.c)
case .right: return (currentPoint.r, currentPoint.c+1)
}
}
var back: Point {
switch currentDir {
case .up: return (currentPoint.r+1, currentPoint.c)
case .left: return (currentPoint.r, currentPoint.c+1)
case .down: return (currentPoint.r-1, currentPoint.c)
case .right: return (currentPoint.r, currentPoint.c-1)
}
}
그리고 네 방향에 청소할 곳이 있는지 확인하는 함수를 하나 만들었는데요,
가능하다면 해당 위치로 바꿔주고 true를 아니라면 false를 리턴해주도록 했습니다.
func availableNextClean() -> Bool {
for _ in 0..<4 {
currentDir.turnLeft()
if map[front.r][front.c] == 0 {
currentPoint = front
return true
}
}
return false
}
마지막으로 이를 종합해주면 됩니다.
현재 위치가 벽일 때까지 while문을 돌렸는데요,
현재 위치를 청소해야하면 하고 (청소하고나면 2로 바꿔줬습니다.)
아니라면 다음 위치로 이동이 가능한지 확인하고
못한다면 빽을 해줬습니다. (빽을 한 위치가 벽이라면 다음 턴에서 종료되겠죠 :))
func runCleaner() {
while map[currentPoint.r][currentPoint.c] != 1 {
if map[currentPoint.r][currentPoint.c] == 0 {
map[currentPoint.r][currentPoint.c] = 2
cleanCount += 1
}
if !availableNextClean() {
currentPoint = back
}
}
}
해결방법
// 14503 로봇청소기
let nm = readLine()!.split(separator: " ").map { Int(String($0))! }
let rcd = readLine()!.split(separator: " ").map { Int(String($0))! }
var map = [[Int]]()
for _ in 0..<nm[0] {
map.append(readLine()!.split(separator: " ").map { Int(String($0))! })
}
typealias Point = (r: Int, c: Int)
enum Direction: Int {
case up = 0, right, down , left
mutating func turnLeft() {
switch self {
case .up: self = .left
case .left: self = .down
case .down: self = .right
case .right: self = .up
}
}
}
var currentDir = Direction(rawValue: rcd[2])!
var currentPoint = Point(rcd[0], rcd[1])
var front: Point {
switch currentDir {
case .up: return (currentPoint.r-1, currentPoint.c)
case .left: return (currentPoint.r, currentPoint.c-1)
case .down: return (currentPoint.r+1, currentPoint.c)
case .right: return (currentPoint.r, currentPoint.c+1)
}
}
var back: Point {
switch currentDir {
case .up: return (currentPoint.r+1, currentPoint.c)
case .left: return (currentPoint.r, currentPoint.c+1)
case .down: return (currentPoint.r-1, currentPoint.c)
case .right: return (currentPoint.r, currentPoint.c-1)
}
}
var cleanCount = 0
func availableNextClean() -> Bool {
for _ in 0..<4 {
currentDir.turnLeft()
if map[front.r][front.c] == 0 {
currentPoint = front
return true
}
}
return false
}
func runCleaner() {
while map[currentPoint.r][currentPoint.c] != 1 {
if map[currentPoint.r][currentPoint.c] == 0 {
map[currentPoint.r][currentPoint.c] = 2
cleanCount += 1
}
if !availableNextClean() {
currentPoint = back
}
}
}
runCleaner()
print(cleanCount)
배운점
구현이 쬐끔 오래걸렸고 back 구현에서 위랑 아래를 거꾸로 써서 2번 예제를 한 40 몇번까지 디버깅했던 것 같다... 후우....ㅂㄷㅂㄷ
그리고 문제에서 서쪽이 1인데 동쪽을 1로 하고 돌려서 틀려서 또 애를 먹었따..
실수 그만!!!