• 백준 14503번 로봇 청소기 :: 마이구미
    알고리즘 풀이/그래프 2017. 10. 28. 17:34
    반응형

    이 글은 백준 알고리즘 문제 14503번 "로봇 청소기" 를 풀이한다.

    삼성 SW 역량 테스트 문제 중 하나의 문제이다.

    본인은 BFS를 활용한 풀이를 설명할 것이다.

    문제 링크 - https://www.acmicpc.net/problem/14503

    BFS 이해 - http://mygumi.tistory.com/102


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

    로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다.

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

    1. 현재 위치를 청소한다.
    2. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
      1. 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
      2. 왼쪽 방향에 청소할 방향이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
      3. 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
      4. 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.

    로봇 청소기는 이미 청소되어있는 칸을 또 청소하지 않으며, 벽을 통과할 수 없다.


    BFS를 응용하여 로봇이 작동 순서 그대로 이동하는 것을 구현했다.

    로봇은 항상 왼쪽 방향만으로만 이동한다는 것을 활용해야한다.

    그래서 코드를 보면, 큐의 사이즈는 항상 1 이하일 것이다.

    BFS 특성을 활용해 4번의 작동은 큐가 비었다는 것을 의미하기에, 신경쓰지 않았다.


    작동 순서에 따른 회전과 후진을 위한 방향만을 잘 지정해주면 문제는 쉽게 해결된다.

    작동 순서 그대로를 구현했기 때문에, 설명보다는 코드를 통해 이해하면 된다.


    그래프 알고리즘 문제 풀이 - 그래프 문제 카테고리

    Github - https://github.com/hotehrud/acmicpc/tree/master/graph


    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    static int[][] map = new int[50][50];
    static int[] dx = { 010-}; // 북 동 남 서
    static int[] dy = { -101};
    static boolean[][] visited = new boolean[50][50];
    static Robot start;
    static int m, n, ans;
     
    private void solve() {
        m = sc.nextInt();
        n = sc.nextInt();
     
        int s = sc.nextInt();
        int e = sc.nextInt();
        int d = sc.nextInt();
     
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                map[i][j] = sc.nextInt();
            }
        }
     
        start = new Robot(s, e, d);
        visited[s][e] = true;
     
        bfs();
        System.out.println(ans + 1);
    }
     
    public static void bfs() {
        Queue<Robot> q = new LinkedList<>();
        q.add(start);
     
        while (!q.isEmpty()) {
            Robot pos = q.poll();
            int d = pos.d;
            int y = pos.r;
            int x = pos.c;
     
            int nextDirection = d;
            int nx = 0;
            int ny = 0;
            boolean flag = false;
     
            // 왼쪽 방향에 청소하지 않은 구역 탐색
            for (int i = 0; i < 4; i++) {
                nextDirection = turnDirection(nextDirection);
                nx = dx[nextDirection] + x;
                ny = dy[nextDirection] + y;
                if (<= nx && nx < n && <= ny && ny < m) {
                    if (map[ny][nx] == && !visited[ny][nx]) {
                        visited[ny][nx] = true;
                        ++ans;
                        q.add(new Robot(ny, nx, nextDirection));
                        flag = true;
                        break;
                    }
                }
            }
     
            // 후진
            if (!flag) {
                nextDirection = backDirection(d);
                nx = dx[nextDirection] + x;
                ny = dy[nextDirection] + y;
     
                if (<= nx && nx < n && <= ny && ny < m) {
                    if (map[ny][nx] == 0) {
                        q.add(new Robot(ny, nx, d));
                    }
                }
            }
     
        }
    }
     
    public static int backDirection(int d) {
        if (d == 0) {
            return 2;
        } else if (d == 1) {
            return 3;
        } else if (d == 2) {
            return 0;
        } else {
            return 1;
        }
    }
     
    public static int turnDirection(int d) {
        // 0 북, 1 동, 2 남, 3 서
        if (d == 0) {
            return 3;
        } else if (d == 1) {
            return 0;
        } else if (d == 2) {
            return 1;
        } else {
            return 2;
        }
    }
     
    public static class Robot {
        int r;
        int c;
        int d;
     
        Robot(int r, int c, int d) {
            this.r = r;
            this.c = c;
            this.d = d;
        }
    }
    cs


    반응형

    댓글 3

    • Favicon of https://mygumi.tistory.com 마이구미 mygumi 2019.09.17 23:02 신고

      rmsgudxx@gmail.com - 마이구미님 풀이 잘 보았습니다. 코드를 보다가 질문이 있어서요. 북0 1동 2남 3서 이 값들은 임의로 정하신건가요?
      => 네네 임의로 정한겁니다~ 감사합니다!

    • Favicon of https://mygumi.tistory.com 마이구미 mygumi 2019.09.17 23:03 신고

      함함 - 풀이 감사하게 보고있습니다! 아직 초보라 질문 하나만 드려도 될까요?
      boolean flag의 의미를 아직 잘 모르겠습니다. 저게 어떤 의미를 가지고 있는지 설명 부탁 드려도 될까요?
      감사합니다
      => 감사합니다~
      후진을 위함입니다. (2번의 3번을 읽어보시길 바랍니다.)
      왼쪽방향부터 차례대로 4군데를 확인하면서 후진 여부를 체크하기 위해 사용합니다.

    • Favicon of https://mygumi.tistory.com 마이구미 mygumi 2019.09.17 23:03 신고

      단데기 - 마이구미님 너무 유용한 글들 잘보고 있습니다! 죄송하지만 github 404 에러뜨는데 수정좀 부탁드려도 되겟습니까? ㅜ
      => 수정하였습니다 ~ 또 발견하신다면 알려주시면...감사합니다

Designed by Tistory.