Algorithm/이코테

11.뱀

마닐라 2022. 1. 6. 14:11

📍 문제 설명

💡 접근

비슷한 문제를 풀었던 것 같은데, 뱀의 방향 변환 정보에 대한 처리가 미흡해서 그 부분은 풀이를 참고했다.

nx, ny를 이용해서 뱀을 이동시키고 벽이나 자기 몸에 부딪히는지 확인하면 되는 문제였다.

사과가 없을 때 꼬리를 잘라내야하므로 큐를 이용해서 꼬리 부분을 0으로 만들어주었다.

 

그리고 방향 전환 시각이 되면 동남서북 or 동북서남으로 이동할 수 있게 turn 메서드를 이용했다.

 

 

👩‍💻 코드

import java.util.*;

public class Main {
    //90도 회전을 위한 배열(동남서북 순으로 저장)
    public static int[] dx = {0,1,0,-1};
    public static int[] dy = {1,0,-1,0};
    public static ArrayList<Node> list = new ArrayList<>();

    public static void main(String[] args) {
        Scanner kb = new Scanner(System.in);

        //보드의 크기
        int n = kb.nextInt();
        int[][] board = new int[n+1][n+1];
        //사과의 개수
        int k = kb.nextInt();
        for(int i = 0; i < k; i++) {
            int a = kb.nextInt();
            int b = kb.nextInt();
            board[a][b] = 1;
        }

        //뱀의 방향 변환 횟수
        int l = kb.nextInt();
        for (int i = 0; i < l; i++) {
            int x = kb.nextInt();
            char c = kb.next().charAt(0);
            list.add(new Node(x, c));
        }
        //1,1에서 시작 처음 방향은 오른쪽
        //D - 오른쪽 L - 왼쪽
        //3초가 지난뒤 오른쪽으로 90도 회전
        //15초가 지난뒤 왼쪽으로 90도 회전
        //17초가 지난뒤 오른쪽으로 90도 회전
        System.out.println(solution(board, n));
    }

    private static int solution(int[][] board, int n) {
        //뱀의 시작 위치
        int x = 1; int y = 1;
        //뱀의 현재 위치는 2로 표시
        board[x][y] = 2;
        //뱀이 바라보고 있는 위치(처음은 동쪽)
        int direction = 0;
        //게임 경과시간
        int time = 0;
        //다음에 회전해야할 정보(시간, 위치)
        int index = 0;

        //뱀의 좌표를 넣기
        //꼬리를 제거시키기 위해서
        Queue<Point> q = new LinkedList<>();
        q.offer(new Point(x, y));

        //뱀 이동 시키기
        while(true) {
            int nx = x + dx[direction];
            int ny = y + dy[direction];
            System.out.println(q);
            //위치를 벗어나지 않고 자기 몸과 부딪히지 않으면 이동시키기
            if(nx >= 1 && ny >= 1 && nx <= n && ny <= n && board[nx][ny] != 2) {
                //사과가 없다면 이동 후에 꼬리를 제거(몸길이 그대로)
                if(board[nx][ny] == 0) {
                    //뱀의 현재 위치를 변경
                    board[nx][ny] = 2;
                    //그 좌표를 큐에 삽입
                    q.offer(new Point(nx, ny));
                    //꼬리 제거
                    Point p = q.poll();
                    board[p.x][p.y] = 0;
                }
                //사과가 있다면 이동만 시키기(몸길이 증가)
                else if(board[nx][ny] == 1) {
                    //뱀의 현재 위치를 변경
                    board[nx][ny] = 2;
                    q.offer(new Point(nx, ny));
                }
            }
            //게임 끝났으면
            else {
                time++;
                break;
            }

            time++;

            //이동한 위치를 현재 좌표로 변경
            x = nx;
            y = ny;

            //뱀의 방향 전환 시각이 되면 방향을 전환시킨다.
            if(time == list.get(index).time) {
                direction = turn(direction, list.get(index).direction);
                index++;
            }

        }

        return time;
    }

    private static int turn(int direction, char c) {
        //왼쪽회전이면 동 -> 북
        if(c == 'L') direction = (direction == 0) ? 3 : direction - 1;
        //오른쪽회전이면 동 -> 남
        else direction = (direction == 3) ? 0 : direction + 1;
        return direction;
    }

    private static class Point {
        private int x;
        private int y;
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
        @Override
        public String toString() {
            return "Point{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    private static class Node {
        private int time;
        private char direction;
        public Node(int time, char direction) {
            this.time = time;
            this.direction = direction;
        }
    }
}

'Algorithm > 이코테' 카테고리의 다른 글

13.치킨 배달  (0) 2022.01.06
12.기둥과 보 설치  (0) 2022.01.06
10.자물쇠와 열쇠  (0) 2021.12.11
9.문자열 압축  (0) 2021.12.11
8.문자열 재정렬  (0) 2021.12.11