[백준] #14503. 로봇 청소기

MTTW·2021년 4월 20일
0

Problem Solving

목록 보기
11/11
post-thumbnail

문제는 여기서 확인할 수 있다. BaekJoon #14503. 로봇 청소기


📌 POINT

문제에서 주어진 작동 방식을 그대로 구현한다.

  • 이런 조건 많은 시뮬레이션은 임의로 편하게 구현하는 것보다는 걍 있는 그대로 구현하는게 제일 빠른듯하다.

주의할 점

  • 조건 그대로 구현하다보니 2.c.는 한 바퀴 돌면서 확인해야한다. 방향을 인덱스로 바꿔서 for문으로 처리해버리는데 방향 헷갈리니 주의
  • index out of range 없도록 조건 잘 잡기
  • 이동이 불가능한 상황에 out of range도 있을 수 있다는 사실 (끝 줄은 모두 벽으로 채운다지만 어디로 튈지 모르니 주의)

🚀 풀이

READY

  • 방향 => 인덱스
    문제에서 나온대로 인덱스를 #define하고 그 순서대로 mx[], my[]를 만든다.
    index out of range를 방지하기 위해 check_range() 메소드를 만드는게 편하다.
#define NORTH 0
#define WEST 1
#define SOUTH 2
#define EAST 3

int mx[] = {-1, 0, 1, 0};
int my[] = {0, 1, 0, -1};

bool check_range(int a, int b, int n, int m){
    if(a<0 || b<0 || a>=n || b>=m) return false;
    return true;
}
  • 빙글빙글 돌지만 왼쪽 한 방향으로 이동한다. 여러번 사용되니 중복을 막기위해 private 메소드로 만들었다.
int left_dir(int d){
     int left = d - 1;
     if(left < 0) left += 4;
     return left;
}

GO

청소기의 움직임은 크게 두 쪼갈 낼 수 있다.
잘 쪼개두면 디버깅이 쉽다

cleaner cleaner_machine(x, y, d);
bool iscleaned = false;
bool isover = false;
int count_cleaned_floor = 0;

while(true){
    iscleaned = cleaner_machine.clean(n, m);
    isover = cleaner_machine.move(n, m);
    if(iscleaned) count_cleaned_floor++;
    if(!isover) break;
}
printf("%d", count_cleaned_floor);

1. bool clean()

현재 위치에서 청소할 수 있으면 칸을 CLEANED로 바꾸고 True를 리턴한다. 리턴값이 True인지 확인해서 청소한 칸을 카운트할 수 있다.
굳이 왜 이걸 나누냐면 청소는 못한 채 두, 세번은 왼쪽으로만 돌거나 후진하는 상황이 생기기 때문이다.

bool clean(int n, int m){
    if(room[x][y] == NOT_CLEANED) {
        room[x][y] = CLEANED;
        return true;
    }
    else return false;
}

2. bool move()

현재 위치에서 회전 및 이동이 이루어지는 메소드다.
종료 조건을 만족하면 False를 리턴한다.

  1. 왼쪽 칸을 청소할 수 있는가
    • 있다면 왼쪽으로 회전하고 직진
  2. 한바퀴를 돌면서 사방이 모두 청소 불가능한지 확인
    • 불가능하다면 뒤가 막혔는지 확인 - WALL인지
      • 막혔다면 종료 : return false;
      • 막히지 않았다면 후진
    • 청소 가능한 방향이 있다면 왼쪽으로 회전
  3. return true;
bool move(int n, int m){
    // check_left
    int left = left_dir(dir);
    int nx = x + mx[left];
    int ny = y + my[left];
    if(is_not_cleaned(nx, ny, n, m)){
        dir = left;
        x = nx; y = ny;
        return true;
    }
    else {
        int turn_dir = left;
        bool is_stucked = true;
	// check four side
        for(int i=0; i<3; i++){
            turn_dir = left_dir(turn_dir);
            if(is_not_cleaned(x + mx[turn_dir], y + my[turn_dir], n, m)){
                is_stucked = false;
            }
        }

	// all cleaned
        if(is_stucked){
            int back = left_dir(left);
            int bx = x + mx[back];
            int by = y + my[back];
 
            if(!check_range(bx, by, n, m) || room[bx][by] == WALL){
                // end condition
   		return false;
            }
            else {  // go back
                x = bx; y = by;
            }
        }
        else { // just turn left
            dir = left;
        }

        return true;
    }
}
profile
개발자가 되고 싶은 맽튜

0개의 댓글