알고리즘/백준

[BOJ] 백준 3190 뱀 (JAVA)

오딩이 2022. 4. 7. 03:12

출처 : https://www.acmicpc.net/problem/3190

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

 

 

🔍 Solve

문제 그대로 따라 하는 시뮬레이션 문제입니다.

해당 문제는 방향을 전환하는 문제이므로, 방향 배열을 순서를 지켜서 만들어야 합니다.

저는 동->남->서->북 순서로 시계방향으로 돌아가는 순서로 만들었습니다.

방향을 전환할 때 L(왼쪽으로 90도)라면 방향 배열의 인덱스를 -1해주고, D(오른쪽으로 90도)라면 방향배열의 인덱스를 +1 해주었습니다. (0~4의 범위를 벗어날 때 예외처리 주의)

 

queue를 사용하여 뱀의 머리와 몸통, 꼬리를 관리해주었고, map배열에 뱀이 있는 위치는 1, 사과가 있는 위치는 2로 설정하여 관리했습니다.

queue를 사용하여 뱀의 머리가 갈 위치가 

1. 벽 ( !isIn(r, c) )

2. 뱀 자신의 몸통 ( map[r][c]==1 )

3. 사과 ( map[r][c]==2 )

4. 빈 곳

으로 나누어 해당 함수를 탈출하거나, queue, map을 처리해주었습니다.

 

해당 문제를 다 풀고 다른 분들의 풀이와 비교해보니 move함수를 time으로 반환하신 분들이 많았는데, 저는 time변수를 전역 변수로 설정하여 어떤 방법을 사용하시더라도 상관없을 것 같습니다.

 

또한, 저는 방향 정보를 HashMap을 사용하여 방향을 전환해야 할 time이 되었을 때 HashMap의 contains 메소드를 사용하여 편리하게 방향 정보를 받아왔습니다.

 

Code

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

public class Main {
    //구현

    static int N; //보드의 크기
    static int K; //사과의 개수
    static int[][] map;  //1 : 뱀 위치, 2 : 사과 위치
    static int L; //뱀의 방향 변환 횟수
    static int[] dr = {0, 1, 0, -1};  //동>남>서>북
    static int[] dc = {1, 0, -1, 0};
    static int time;
    static HashMap<Integer, String> directs = new HashMap<>();  //배열대신 hashmap

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

        N = Integer.parseInt(br.readLine()); //보드의 크기
        K = Integer.parseInt(br.readLine()); //사과의 개수

        map = new int[N+2][N+2];  //r,c==0이거나 r,c==N+1이면 벽에 도착
        for(int i=0;i<K;i++){
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            map[r][c] = 2; //사과
        }

         L = Integer.parseInt(br.readLine());

        for(int i=0;i<L;i++){
            st = new StringTokenizer(br.readLine());
            int turn = Integer.parseInt(st.nextToken());
            String d = st.nextToken();

            directs.put(turn, d);

        }
        move();
        System.out.println(time);
    }

    private static void move(){
        Queue<Pos> queue = new LinkedList<>();

        queue.add(new Pos(1, 1));
        int d = 0; //오른쪽먼저
        int cr = 1;
        int cc = 1;
        map[1][1] = 1;  //뱀

        while(!queue.isEmpty()){
            time++;

            int nr = cr+dr[d];
            int nc = cc+dc[d];

            if(!isIn(nr, nc)) return;  //범위 벗어나면(벽에 부딪힘) 탈출
            if(map[nr][nc]==1){ // 뱀이 자기 몸에 부딪히면 탈출
                return;
            }

            if(map[nr][nc]==2){  //다음 위치가 사과면 머리만 길어짐
                queue.add(new Pos(nr, nc));
                map[nr][nc] = 1;
            }else{  //사과가 아니면
                queue.add(new Pos(nr, nc));  //머리 이동하고
                Pos remove = queue.poll();  //꼬리 자름
                map[nr][nc] = 1;  //뱀 머리위치 1로
                map[remove.r][remove.c] = 0;  //자른위치는 다시 0으로
            }

            if(directs.containsKey(time)){ //해시맵에 현재 시간이 포함되어있다면 방향 전환
                String dir = directs.get(time);
                if(dir.equals("L")){
                    d -= 1;
                    if(d<0){
                        d = 4+d;
                    }
                }else{
                    d = (d+1)%4;
                }
            }
            cr = nr;
            cc = nc;
        }
    }

    private static boolean isIn(int r, int c){
        return r>0 && c>0 && r<=N && c<=N;
    }


    private static class Pos{
        int r;
        int c;

        public Pos(int r, int c) {
            this.r = r;
            this.c = c;
        }

        @Override
        public String toString() {
            return "Pos{" +
                    "r=" + r +
                    ", c=" + c +
                    '}';
        }
    }
}
728x90