Hansel

백준_14503(BFS) 본문

알고리즘과 자료구조/BFS&DFS

백준_14503(BFS)

핑슬 2022. 2. 15. 23:44

 

로봇 청소기의 동작 방식만 본다면 어려울게 없는 문제이긴 하다.

문제는 내 코드가 너무 정직하게 구현한 코드이고 뭔가 논리적인 부분이 보이질 않는다.

 

이 문제는 삼성 sw역량테스트 문제였다고 하는데 내 코드가 테스트케이스를 다 통과해도 코드리뷰에서 아마 탈락하지 않았을까 싶다.

package Feb_2022;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Boj_14503 {
    static int N; // 세로
    static int M; // 가로
    static int[][] map;
    static boolean[][] clean;
    static int result = 0;

    static Point start;

    public static class Point {
        int y;
        int x;
        int p; //방향

        public Point(int y, int x, int p) {
            this.y = y;
            this.x = x;
            this.p = p;
        }
    }

    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        map = new int[N][M];
        clean = new boolean[N][M];
        st = new StringTokenizer(br.readLine()); // 시작 좌표 입력

        //시작 좌표
        int y = Integer.parseInt(st.nextToken());
        int x = Integer.parseInt(st.nextToken());
        int p = Integer.parseInt(st.nextToken()); // 방향
        start = new Point(y,x,p);
        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());
            }
        }

        bfs();
        System.out.println(result);
        //1.현재 위치를 청소
        //2.현재 위치에서 현재 방향을 기준으로 왼쪽부터 탐색
        //왼쪽에 청소 안되어있으면 거기로 회전하고 전진하고 1번
        //왼쪽에 청소할 공간 없으면 그 방향으로 회전하고 2번
        //네 방향 모두 청소거나 벽이면 바라보는 방향 유지하면서 후진하고 2번
        //네 방향 모두 청소고 벽이고 후진 안되면 작동 중지

    }

    // 북-0 , 동 -1, 남-2, 서-3
    private static void bfs() {
        Queue<Point> q = new LinkedList<>();
        q.offer(start);

        while(!q.isEmpty()){
            Point now = q.poll();
            //1.현재 위치를 청소
            if(map[now.y][now.x]==0 && clean[now.y][now.x]==false){
                result++;
                clean[now.y][now.x] = true;
            }
            //2.현재 위치에서 현재 방향을 기준으로 왼쪽부터 탐색
            Point next = direction(now.y,now.x,now.p);
            if(next==null){
                break;
            }
            else{
                q.offer(next);
            }
//            for (int i = 0; i < N; i++) { //지도 입력
//                for (int j = 0; j < M; j++) {
//                    System.out.print(clean[i][j] + " ");
//                }
//                System.out.println();
//            }
//            System.out.println("====================");
//            System.out.println(next.y + " " + next.x + " " + next.p);
//            System.out.println("====================");
        }
        //왼쪽에 청소 안되어있으면 거기로 회전하고 전진하고 1번
        //왼쪽에 청소할 공간 없으면 그 방향으로 회전하고 2번
        //네 방향 모두 청소거나 벽이면 바라보는 방향 유지하면서 후진하고 2번
        //네 방향 모두 청소고 벽이고 후진 안되면 작동 중지
    }

    private static Point direction(int y,int x,int p) {
        int originP=p;
        // 북-0 , 동 -1, 남-2, 서-3
        //2.현재 위치에서 현재 방향을 기준으로 왼쪽부터 탐색
        //왼쪽에 청소 안되어있으면 거기로 회전하고 전진하고 1번
        int turn = 0; //4번 회전하면 종료하도록
        while(turn < 4){
            if(p==0){//북쪽을 바라보고 있는 경우
                int nx = x-1;
                p = 3;
                turn++;
                //왼쪽이 청소가 안되어있는 경우
                if(y >= 0 && nx >=0 && y < N && x < M && map[y][nx]==0 && clean[y][nx]==false){
                    return new Point(y,nx,p);
                }
            }
            else if(p==1){//동쪽을 바라보고 있는 경우
                int ny = y-1;
                p = 0;
                turn++;
                //왼쪽이 청소가 안되어있는 경우
                if(ny >= 0 && x >=0 && ny < N && x < M && map[ny][x]==0 && clean[ny][x]==false){
                    return new Point(ny,x,p);
                }
            }
            else if(p==2){//남쪽을 바라보고 있는 경우
                int nx= x + 1;
                p = 1;
                turn++;
                //왼쪽이 청소가 안되어있는 경우
                if(y >= 0 && nx >=0 && y < N && nx < M && map[y][nx]==0 && clean[y][nx]==false){
                    return new Point(y,nx,p);
                }
            }
            else if(p==3){//서쪽을 바라보고 있는 경우
                int ny = y+1;
                p=2;
                turn++;
                //왼쪽이 청소가 안되어있는 경우
                if(ny >= 0 && x >=0 && ny < N && x < M && map[ny][x]==0 && clean[ny][x]==false){
                    return new Point(ny,x,p);
                }
            }
            //System.out.println("turn : " + turn);
            if(turn==4){ //네 방향 다 돌았는데 return 안한 경우=> 후진
                //System.out.println(y + "* " + x + "*" + p);
                Point next = back(y,x,originP);
                if(next==null){ //후진이 불가능하다면
                    return null;
                }
                else return next;
            }
        }
        //네 방향 모두 청소거나 벽이면 바라보는 방향 유지하면서 후진하고 2번
        return null;
    }

    private static Point back(int y, int x, int p) {
        if(p==0){//북쪽을 바라보고 있는 경우
            int ny = y+1;
            // 후진이 가능한 경우
            if(ny >= 0 && x >=0 && ny < N && x < M && map[ny][x]!=1){
                return new Point(ny,x,0);
            }
        }
        if(p==1){//동쪽을 바라보고 있는 경우
            int nx = x-1;
            if(y >= 0 && nx >=0 && y < N && nx < M && map[y][nx]!=1){
                return new Point(y,nx,1);
            }
        }
        if(p==2){//남쪽을 바라보고 있는 경우
            int ny = y-1;
            if(ny >= 0 && x >=0 && ny < N && x < M && map[ny][x]!=1){
                return new Point(ny,x,2);
            }
        }
        if(p==3){//서쪽을 바라보고 있는 경우
            int nx = x+1;
            if(y >= 0 && nx >=0 && y < N && nx < M && map[y][nx]!=1){
                return new Point(y,nx,3);
            }
        }
        //후진이 불가능하다.
        return null;
    }


}

'알고리즘과 자료구조 > BFS&DFS' 카테고리의 다른 글

백준_15650(DFS)  (0) 2022.03.08
백준_1261(0-1 BFS)  (0) 2022.03.03
백준_14502(BFS)  (0) 2022.02.11
백준_14500(DFS)  (0) 2022.02.10
백준_1260(DFS&BFS)  (0) 2022.02.04