Java알고리즘

[BOJ][Java]Q2174 - 로봇 시뮬레이션

앙두딘 2022. 4. 5. 19:42
 

2174번: 로봇 시뮬레이션

첫째 줄에 두 정수 A, B가 주어진다. 다음 줄에는 두 정수 N, M이 주어진다. 다음 N개의 줄에는 각 로봇의 초기 위치(x, y좌표 순) 및 방향이 주어진다. 다음 M개의 줄에는 각 명령이 명령을 내리는 순

www.acmicpc.net

 

크게 어려운 점은 없는 문제인데, 

board의 방향이 좌표평면과 똑같다는 점에서 유의해야 했다.

board[B+1][A+1] 크기로 선언해야하고, 나는 로봇의 x, y좌표를 입력받을 때 y좌표를 뒤집어서 저장해 주었다.

( 1,2,3,4) -> 각각 (4,3,2,1)로 저장

그 이후로는 내 행렬 모양대로 풀었다.

 

1. 로봇정보 저장

로봇행렬을 만들어서 각 인덱스에 로봇정보(로봇의 방향, x좌표, y좌표)를 저장하고,
int[][] board에는 로봇번호를 저장했다.

 

 

2. 방향전환

static char[] rotate = new char[]{'N','E','S','W'};

 

시계 방향 순서를 저장해놓고, 다음 방향을 찾는다.

LEFT회전의 경우, 현재 방향의 인덱스를 찾고, 1 감소시킨다.(0보다 작아지면 3으로 돌아감)

RIGHT회전의 경우, 현재 방향의 인덱스를 찾고 1 증가시킨다.(4보다 커지지 않도록 %4처리)

//아래코드는 RIGHT회전 코드

for(int dirIndex = 0; dirIndex<4; dirIndex++){
    //현재 방향 찾아서 다음 인덱스로 바꿈
    if(left_rotate[dirIndex] == nowDir){
        dirIndex = (dirIndex+1)%4;
        robots[robotNum].dir = left_rotate[dirIndex];
        break;
    }
}

(사실 dx, dy배열을 이용해 시계방향 순서대로 저장하고, 현재 방향을 int형 인덱스 값으로 저장하면 따로 현재방향의 인덱스를 찾아줄 필요가 없어서 이것보다 더 좋은 코드일 것 같다.)

 

3. 한칸 앞으로 이동

dx, dy 배열을 사용해 상하좌우로 이동한다.

로봇이 향하고 있는 방향에 따라 이동할 칸을 찾고, 충돌을 검사한다.
- 그 칸이 벽과 충돌하는지(0 or A+1/B+1) 
- 다른 로봇과 충돌하는지(board값이 0이 아님)

 

충돌하지 않는 경우,
board값을 바꿔주고(현재값: 0, 이동할 위치: 로봇번호)

로봇 배열의 좌표도 바꿔준다.

 

전체 코드

package simulation;

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

public class Q2174_로봇시뮬레이션 {
    /*[골드5] Q2174 - 로봇 시뮬레이션*/
    static int A, B, N, M;
    static char[] rotate = new char[]{'N','E','S','W'}; //시계방향(right)

    static int [] dx = new int[]{0,0,-1,1}; //N,S,W,E 순서
    static int [] dy = new int[]{-1,1,0,0};


    static int[][] board;   //로봇이 위치하면 로봇 번호 저장, 아니면 0저장
    static Robot[] robots;

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

        A = Integer.parseInt(st.nextToken());
        B = Integer.parseInt(st.nextToken());
        board = new int[B+1][A+1]; //1부터 사용

        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        robots = new Robot[N+1];    //1부터 사용
        M = Integer.parseInt(st.nextToken());

        //로봇의 초기 위치
        for(int i = 1; i<N+1; i++){
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int y = (B+1)-Integer.parseInt(st.nextToken()); //뒤집어서 저장
            char dir = st.nextToken().charAt(0);
            robots[i] = new Robot(x,y,dir);
            board[y][x] = i;
        }

        for(int i = 0; i<M;i++){
            st = new StringTokenizer(br.readLine());
            int robotNum = Integer.parseInt(st.nextToken());
            char order = st.nextToken().charAt(0);
            int times = Integer.parseInt(st.nextToken());

            //times만큼 반복
            for(int t = 0; t<times; t++){
                char nowDir = robots[robotNum].dir;
                switch(order){
                    case 'L':
                        //다음 방향을 찾는다.
                        for(int dirIndex = 0; dirIndex<4; dirIndex++){
                            //현재 방향 찾아서 다음 인덱스로 바꿈
                            if(rotate[dirIndex] == nowDir){
                                dirIndex = (dirIndex-1)<0? 3 : dirIndex-1;
                                robots[robotNum].dir = rotate[dirIndex];
                                break;
                            }
                        }
                        break;

                    case 'R':
                        //다음 방향을 찾는다.
                        for(int dirIndex = 0; dirIndex<4; dirIndex++){
                            if(rotate[dirIndex] == nowDir){
                                dirIndex = (dirIndex+1)%4;
                                robots[robotNum].dir = rotate[dirIndex];
                                break;
                            }
                        }
                        break;

                    case 'F':
                        //한칸 앞으로 이동했을 때 좌표 구하기
                        int fowardIndex = -1;
                        switch(nowDir){
                            case 'N':
                                fowardIndex = 0;
                                break;
                            case 'S':
                                fowardIndex = 1;
                                break;
                            case 'W':
                                fowardIndex = 2;
                                break;
                            case 'E':
                                fowardIndex = 3;
                                break;
                        }
                        int nextX = robots[robotNum].x + dx[fowardIndex];
                        int nextY = robots[robotNum].y + dy[fowardIndex];

                        //벽과 충돌하는지(0 또는 A+1/B+1)
                        if(nextX==0 || nextX==A+1 || nextY ==0 || nextY == B+1){
                            System.out.println("Robot "+robotNum+" crashes into the wall");
                            System.exit(0);
                        }
                        //로봇과 충돌하는지(board가 0이 아님)
                        if(board[nextY][nextX] != 0){
                            System.out.println("Robot "+robotNum+" crashes into robot "+board[nextY][nextX]);
                            System.exit(0);
                        }

                        board[robots[robotNum].y][robots[robotNum].x] = 0;
                        board[nextY][nextX] = robotNum;
                        robots[robotNum].x = nextX;
                        robots[robotNum].y = nextY;
//                        System.out.println("("+robotNum+") "+nextX+" "+nextY+" "+nowDir);
                        break;
                }
            }
        }
        System.out.println("OK");
    }
    static class Robot{
        int x, y;
        char dir;

        public Robot() {
        }

        public Robot(int x, int y, char dir) {
            this.x = x;
            this.y = y;
            this.dir = dir;
        }
    }
}