곽로그

[백준 14503 ,Java] 로봇 청소기 본문

알고리즘/백준

[백준 14503 ,Java] 로봇 청소기

일도이동 2021. 4. 8. 15:50
반응형

1. 문제

www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

 

2. 이 문제에서 배울 점

- 순서도 그리기! 

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

위의 로직을 순서도로 그리면 c)에서 2번으로 가야하는데, 나는 1번으로 갔다. 

그래서 1번에서 처리를 할 때 청소가 되어있는지 아닌지를 다시 한번 확인해야했다. 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

class Cleaner{
    int x, y, direction,cleanedCount;
    Cleaner(int x, int y, int direction, int cleanedCount){
        this.x = x;
        this.y =y ;
        this.direction = direction;
        this.cleanedCount = cleanedCount;
    }

    @Override
    public String toString() {
        return "Cleaner{" +
                "x=" + x +
                ", y=" + y +
                ", direction=" + direction +
                ", cleanedCount=" + cleanedCount +
                '}';
    }
}
public class Main {
    static int[][] map;
    static int N;
    static int M;
    static final int EMPTY = 0;
    static final int WALL = 1;
    static int[] dx = {-1, 0, 1,0};
    static int[] dy = {0,  1, 0,-1};

    static Cleaner cleaner;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;

        st = new StringTokenizer(br.readLine(), " ");
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        map = new int[N][M];

        st = new StringTokenizer(br.readLine()," ");
        int r = Integer.parseInt(st.nextToken());
        int c = Integer.parseInt(st.nextToken());
        int d = Integer.parseInt(st.nextToken());
        cleaner = new Cleaner(r, c, d, 0);


        for(int i = 0; i<N; i++){
            st = new StringTokenizer(br.readLine(), " ");
            for(int j =0; j<M; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        int result = func();
        bw.write(String.valueOf(result));
        bw.flush();


    }
    public static int func(){
        boolean[][] cleaned = new boolean[N][M];

        while (true){
            //현재위치를 청소한다 -> 4면이 막혀있는경우 여기로 돌아와서 청소했는지 아닌지 확인해야함
            if(!cleaned[cleaner.x][cleaner.y]){
                cleaned[cleaner.x][cleaner.y] =true;
                ++cleaner.cleanedCount;
            }

            //탐색한다
            boolean moved = false;
            int d = cleaner.direction;
            for(int count = 0; count<4; count++){
                //현재방향 기준 왼쪽 방향부터
                d = (d%4 -1%4 + 4)%4;
                int nx = cleaner.x + dx[d];
                int ny = cleaner.y + dy[d];

                // 청소할 수 있다
                if(isValid(nx, ny)){
                    if(!cleaned[nx][ny] && map[nx][ny]!= WALL){
                        cleaner.x = nx;
                        cleaner.y = ny;
                        cleaner.direction = d;

                        moved = true;
                        break;
                    }
                }
            }

            //청소를 하지 않은 경우
            if(!moved){
                //뒤로 후진할 수 있는지 확인
                int nx = cleaner.x + dx[(cleaner.direction+2)%4];
                int ny = cleaner.y + dy[(cleaner.direction+2)%4];

                if(isValid(nx, ny) && map[nx][ny] ==EMPTY){
                    cleaner.x = nx;
                    cleaner.y = ny;
                }
                else{
                    break;
                }

            }
        }
        return cleaner.cleanedCount;
    }

    public static boolean isValid(int x, int y){
        return x>=0 && x<N && y>=0 && y<M;
    }

}

 

 

 c)에서 2번으로 가야하는 경우는 어떻게 구현해야 할까를 생각해보는데, 

반응형
Comments