블록이동하기

Lee1231234·2024년 4월 15일

코딩테스트

목록 보기
74/95

"0"과 "1"로 이루어진 지도인 board가 주어질 때, 로봇이 (N, N) 위치까지 이동하는데 필요한 최소 시간을 return 하도록 solution 함수를 완성해주세요.

제한사항
board의 한 변의 길이는 5 이상 100 이하입니다.
board의 원소는 0 또는 1입니다.
로봇이 처음에 놓여 있는 칸 (1, 1), (1, 2)는 항상 0으로 주어집니다.
로봇이 항상 목적지에 도착할 수 있는 경우만 입력으로 주어집니다.

맨처음 생각한것

BFS를 이용해 첫값을 넣고 방문자제거를 통해 해결하면 된다.
그런데 많이 봤던 칸이 하나가 아니라 2개를 움직이는것이라면 어떻게 해야하나?
회전이 들어가므로 상하좌우 그리고 회전반경 4개까지 한번에 8개를 체크해야한다.
칸 하나를 고정해서 문제를 풀면 편하게 가능하겠다.

BFS문제이고 구상은 쉽지만 칸이 2개라는점에 대해서 구현이 잘 생각안나는 문제였다.
결국 고정되는 값 하나만 생각하면 구현이 되는문제였다.

코드

import java.util.*;
class Solution {
    public int solution(int[][] board) {
        int answer = Integer.MAX_VALUE;
        //상하좌우
        int[] dx = {-1,1,0,0};
        int[] dy = {0,0,-1,1};
        //회전
        int[][] rx = {{-1,0,-1,0},{0,0,1,1}};
        int[][] ry = {{0,0,1,1},{-1,0,-1,0}};
        boolean[][][] visit = new boolean[2][board.length][board[0].length];
        Queue<robot> queue = new LinkedList<>();
        queue.add(new robot(0,0,0,0));
        visit[0][0][0] = true;
        while(!queue.isEmpty()){          
            robot tmp = queue.poll();
            //가로일때
            if(tmp.dir==0&&tmp.x==board.length-1&&tmp.y==board.length-2){
                answer = Math.min(answer,tmp.time);
                continue;
            }
            //세로일때
             if(tmp.dir==1&&tmp.x==board.length-2&&tmp.y==board.length-1){
                answer = Math.min(answer,tmp.time);
                continue;
            }
            //상하좌우
            for(int i=0;i<4;i++){
                int nx = tmp.x + dx[i];
                int ny = tmp.y + dy[i];
                //체크
                if(!checkedBoard(nx,ny,board,tmp.dir)) continue;
                if(!visit[tmp.dir][nx][ny]){                 
                    queue.add(new robot(nx,ny,tmp.dir,tmp.time+1));
                    visit[tmp.dir][nx][ny]=true;
                }
            }
        
            //회전
            for(int i=0;i<4;i++){
                int nx = tmp.x + rx[tmp.dir][i];
                int ny = tmp.y + ry[tmp.dir][i];
                
                //회전가능한지 여부체크를 위한 x,y;
                int cx=0;
                int cy=0;
                int ndir=0;
                if(tmp.dir==0){
                    cx = tmp.x + dx[i%2];
                    cy = tmp.y + dy[i%2];
                    ndir = 1;
                }else{
                    cx = tmp.x + dx[i<2?i+2:i];
                    cy = tmp.y + dy[i<2?i+2:i];
                    ndir = 0;
                }
                if(!checkedBoard(nx,ny,board,ndir)||!checkedBoard(cx,cy,board,tmp.dir)) continue;
                if(!visit[ndir][nx][ny]){
                    queue.add(new robot(nx,ny,ndir,tmp.time+1));
                    visit[ndir][nx][ny]=true;
                }
            }
        }
       
        return answer;
    }
    boolean checkedBoard(int nx,int ny,int[][] board,int dir){
        int n=board.length;
        if(dir==0){
            if(nx<0||ny<0||nx>=n||ny>=n||ny+1>=n||board[nx][ny]!=0||board[nx][ny+1]!=0) return false;            
        }else{
            if(nx<0||ny<0||nx+1>=n||nx>=n||ny>=n||board[nx+1][ny]!=0||board[nx][ny]!=0) return false;
        }
        return true;
    }
    class robot{
        int x;
        int y;    
        int dir;
        int time;
        robot(int x,int y,int dir,int time){
            this.x=x; 
            this.y=y; 
            this.dir=dir;
            this.time=time; 
        }
    }
}//큐를 통한 문제풀이
profile
not null

0개의 댓글