본문 바로가기
알고리즘

[백준14503/시뮬레이션] 로봇 청소기

by 물고기고기 2023. 11. 14.

문제풀이 구상 -> while문을 돌면서 전진시 방위 덧셈, 후진시 방위 뺄셈

1트

public class simulation14503 {

    static int N;
    static int M;
    static int[][] room;
    static int[] nowPoint;
    static int side;

    static int[] dy = {-1, 0, 1, 0}; //우하좌상 동남서북 -> 북동남서0123
    static int[] dx = {0, 1, 0, -1};

    static int cleanUpCount;


    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 첫 줄에서 N과 M을 읽어옵니다.
        N = scanner.nextInt();
        M = scanner.nextInt();

        // 둘째 줄에서 1번과 2번의 값을 nowPoint 배열에 할당하고
        // 3번의 값을 side 변수에 할당합니다.
        nowPoint = new int[2];
        nowPoint[0] = scanner.nextInt();
        nowPoint[1] = scanner.nextInt();
        side = scanner.nextInt();

        // 세 번째 줄부터 마지막 줄까지 room 배열을 읽어옵니다.
        room = new int[N][M];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                room[i][j] = scanner.nextInt();
            }
        }

        // 입력 값을 출력하여 확인할 수 있습니다.
        System.out.println("N: " + N + ", M: " + M);
        System.out.println("nowPoint: " + nowPoint[0] + " " + nowPoint[1]);
        System.out.println("side: " + side);
        System.out.println("room:");
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                System.out.print(room[i][j] + " ");
            }
            System.out.println();
        }
        scanner.close();


        cleanUp();

        System.out.println("cleanUpCount: " + cleanUpCount);
    }

    private static void cleanUp() {
        boolean stop = false;
        while (!stop) {
            if (room[nowPoint[0]][nowPoint[1]] == 0) {
                room[nowPoint[0]][nowPoint[1]] = 1;
                cleanUpCount += 1;
            }

            boolean sideChange = false;
            // 사방으로 청소할 칸이 있는지 검사
            for (int i = 0; i < 4; i++) {
                int y = nowPoint[0] + dy[i];
                int x = nowPoint[1] + dx[i];
                if (room[y][x] == 0) {
                    sideChange = true;
                }
            }

            if (sideChange == true) { // 사방에 청소할 칸이 있다면 해당 방향으로 전진
                int y = nowPoint[0] + dy[side];
                int x = nowPoint[1] + dx[side];

                if (y > 0 && y < N && x > 0 && x < M) { // 벽을 뚫고 나가지 않도록 범위 검사
                    if (room[y][x] == 0) { // 그리고 청소되지 않은 칸이라면 전진
                        nowPoint[0] = y;
                        nowPoint[1] = x;
                    }
                }
            } else {
                // 사방에 청소할 칸이 없다면 해당 방향으로 후진

                int y = nowPoint[0] - dy[side];
                int x = nowPoint[1] - dx[side];

                if (y > 0 && y < N && x > 0 && y < M) { // 벽을 뚫고 나가지 않도록 범위 검사
                    // 이때는 청소된 칸이어도 범위를 넘지않으면 후진
                    nowPoint[0] = y;
                    nowPoint[1] = x;
                }else{
                    stop = true;
                }
            }

        }

    }


}

인데 무한 while문을 돌길래 뭘 고려안했나했더니 엄청나게 고려사항을 빼먹었다

  1. 방향 전환 로직이 누락: 로봇 청소기는 현재 방향을 기준으로 왼쪽 방향부터 청소 가능 여부를 확인하고, 청소할 곳이 있으면 그 방향으로 전진해야 합니다. 청소할 곳이 없으면 계속 왼쪽으로 회전하면서 청소할 곳을 찾아야 합니다. 이 로직이 코드에 구현되어 있지 않습니다.
  2. 방향 회전 로직 오류: sideChange를 사용하는 부분에서 sideChange = true는 비교가 아닌 할당입니다. 따라서 이 조건문은 항상 참이 됩니다. 이를 sideChange == true로 변경해야 합니다.
  3. 벽 검사 로직 오류: if (y > 0 && y < N && x > 0 && y < M) 조건에서 y < M은 x < M이어야 합니다. y 대신 x를 검사해야 벽 검사가 정확해집니다.
  4. 후진 로직 오류: 후진할 때도 현재 방향을 유지해야 합니다. 방향 회전 없이 그대로 뒤로 가야 하므로, 현재 방향의 반대 방향을 계산해야 합니다.
  5. 청소 영역 마킹 방식 오류: room[nowPoint[0]][nowPoint[1]] == 0을 확인한 후 청소했다면 2와 같은 다른 숫자로 마킹해야 합니다. 1은 벽을 나타내기 때문입니다.

벽도 1이고 청소가능한곳도 1로 바꾸면 어떤게 벽이고 청소한 노드인지 구분이 불가능하니 청소한 곳은 2로 해야함. 그 외에도.. 문법 실수등 잘못푼곳이 많음

2트

// ... 이전 코드 ...

private static void cleanUp() {
    boolean stop = false;
    while (!stop) {
        if (room[nowPoint[0]][nowPoint[1]] == 0) {
            room[nowPoint[0]][nowPoint[1]] = 2; // 청소한 곳은 2로 마킹
            cleanUpCount += 1;
        }

        boolean cleaned = false;
        int originalSide = side; // 현재 방향을 저장해둔다.
        
        // 사방으로 청소할 칸이 있는지 검사
        for (int i = 0; i < 4; i++) {
            side = (side + 3) % 4; // 왼쪽으로 회전
            int y = nowPoint[0] + dy[side];
            int x = nowPoint[1] + dx[side];
            
            if (y >= 0 && y < N && x >= 0 && x < M && room[y][x] == 0) {
                nowPoint[0] = y;
                nowPoint[1] = x;
                cleaned = true;
                break; // 청소하러 이동
            }
        }

        if (!cleaned) { // 사방에 청소할 칸이 없다면
            // 반대 방향을 계산하여 후진
            side = (originalSide + 2) % 4; // 반대 방향
            int y = nowPoint[0] + dy[side];
            int x = nowPoint[1] + dx[side];
            
            // 벽이 아니면 후진
            if (y >= 0 && y < N && x >= 0 && x < M && room[y][x] != 1) {
                nowPoint[0] = y;
                nowPoint[1] = x;
            } else {
                stop = true; // 더 이상 후진할 수 없으므로 중지
            }
            side = originalSide; // 방향을 원래대로 돌려놓는다.
        }
    }
}

// ... 이후 코드 ...

 

성공

댓글