코딩테스트/Java

[JAVA] 백준 로봇청소기

SK_MOUSE 2021. 4. 14. 17:27
반응형

실패코드

더보기

어디서부턴가 꼬여버렸다. 모든 케이스를 if문으로 분류하려고 하다가 실패한것이 원인이다.

import java.util.Scanner;

class Main{
    static int N,M,r,c,direction;
    static int[][] grid;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        M = sc.nextInt();
        r= sc.nextInt();
        c= sc.nextInt();
        direction= sc.nextInt();
        grid = new int[N][M];
        for(int i=0; i<N; i++){
            for(int j=0; j<M; j++){
                grid[i][j] = sc.nextInt();
            }
        }
        //(r,c)에서 출발해서 작동방법에따라 움직인다.
        //현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
        if(grid[r][c]==1) System.out.println(0);
        else{
            //왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
            check(r,c, direction, 0);
        }

        int answer=0;
        for(int i=0; i<N; i++){
            for(int j=0; j<M; j++){
                System.out.print(grid[i][j]);
                if(grid[i][j]==2) answer++;
            }
            System.out.println();
        }
        System.out.println(answer);
    }
    static void check(int x, int y, int direct, int directCount){
        grid[x][y] = 2;//청소완료
        System.out.println("("+x+","+y+"): "+ direct + " , " + directCount);
        //네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
        if(directCount == 4){//한바퀴 돌아서 다확인.
            if(x-1>=0&&direct==0&&grid[x-1][y]!=1){//후진가능x--
                check(x-1,y, direct, 0);
            }else if(y-1>=0&&direct==1&&grid[x][y-1]!=1){//후진가능y--
                check(x,y-1, direct, 0);
            }else if(x+1<N&&direct==2&&grid[x+1][y]!=1){//후진가능x++
                check(x+1,y, direct, 0);
            }else if(y+1<M&&direct==3 &&grid[x][y+1]!=1){//후진가능y++
                check(x,y+1, direct, 0);
            }else{//후진불가능
                //네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다
                System.out.println("펑");
            }
            return;
        }

        //왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
        if(direct==0){//좌로 ㄱㄱ
            if(y-1>=0&&grid[x][y-1] == 0){
                check(x,y-1, 3, 0);
            }else if(y-1>=0&&(grid[x][y-1]==1||grid[x][y-1]==2)){
                check(x, y, 3, directCount+1);
            }
        }else if(direct==1){//상으로 ㄱㄱ
            if(x-1>=0&&grid[x-1][y] == 0){
                check(x-1,y, 0,0);
            }else if(x-1>=0&&(grid[x-1][y]==1||grid[x-1][y]==2)){
                check(x, y, 0, directCount+1);
            }
        }else if(direct==2){//우로 ㄱㄱ
            if(y+1<M&&grid[x][y+1] == 0){
                check(x,y+1, 1,0);
            }else if(y+1<M&&(grid[x][y+1]==1||grid[x][y+1]==2)){
                check(x, y, 1, directCount+1);
            }
        }else{//direct==3 하로 ㄱㄱ
            if(x+1<N&& grid[x+1][y] == 0){
                check(x+1,y, 2,0);
            }else if(x+1<N&&(grid[x+1][y]==1||grid[x+1][y]==2)){
                check(x, y, 2, directCount+1);
            }else{
                System.out.println(x+1);
            }
        }
        return;
    }
}

 

아래는 규칙성을 알아낸 참고그림이다.

https://velog.io/@hammii/%EB%B0%B1%EC%A4%80-14503-%EB%A1%9C%EB%B4%87-%EC%B2%AD%EC%86%8C%EA%B8%B0-java

 

clean메소드를 통해서 청소를 하는데, 

 

전체코드는 아래와 같다.

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static int N, M;
    public static int[][] map;
    public static int cnt = 0;
    public static int[] dr = {-1, 0, 1, 0}; // 북,동,남,서
    public static int[] dc = {0, 1, 0, -1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer 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());

        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());
            }
        }
        clean(r, c, d);

        bw.write(cnt + "\n");
        br.close();
        bw.flush();
        bw.close();
    }

    public static void clean(int row, int col, int direction) {
        // 1. 현재 위치를 청소한다.
        if (map[row][col] == 0) {
            map[row][col] = 2;
            cnt++;
        }

        // 2. 왼쪽방향부터 차례대로 탐색을 진행한다.
        boolean flag = false;
        int origin = direction;
        for (int i = 0; i < 4; i++) {
            int next_d = (direction + 3) % 4;
            int next_r = row + dr[next_d];
            int next_c = col + dc[next_d];

            if (next_r > 0 && next_c > 0 && next_r < N && next_c < M) {
                if (map[next_r][next_c] == 0) {   // 아직 청소하지 않은 공간이라면
                    clean(next_r, next_c, next_d);
                    flag = true;
                    break;
                }
            }
            direction = (direction + 3) % 4;
        }

        // 네 방향 모두 청소가 되어있거나 벽인 경우
        if (!flag) {
            int next_d = (origin + 2) % 4;
            int next_br = row + dr[next_d];
            int next_bc = col + dc[next_d];

            if (next_br > 0 && next_bc > 0 && next_br < N && next_bc < M) {
                if (map[next_br][next_bc] != 1) {
                    clean(next_br, next_bc, origin); // 바라보는 방향 유지한 채 후진
                }
            }
        }
    }
}

 

반응형

'코딩테스트 > Java' 카테고리의 다른 글

[JAVA] 백준 아기상어  (0) 2021.04.28
[JAVA] 조합 DP로 풀기 : 백준 다리놓기  (0) 2021.04.21
[JAVA]백준 치킨배달  (4) 2021.04.12
[JAVA] 백준 N과 M(2), DFS 중복X  (0) 2021.03.31
(2018카카오) 파일명정렬 Java  (0) 2021.03.18