Live Today

[백준]17837. 새로운 게임2 (Java) 본문

알고리즘/백준 문제풀이

[백준]17837. 새로운 게임2 (Java)

ilivetoday 2023. 1. 24. 15:29
반응형

https://www.acmicpc.net/problem/17837

 

17837번: 새로운 게임 2

재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하

www.acmicpc.net

  • Queue는 First - In - First - Out 으로 가장 먼저 들어온 데이터가 가장 먼저 나간다.
    • Queue의 2차원 배열로 처음에 구현했었는데 이렇게 하면 현재 탐색하는 말 번호와 같은 칸에 있는 말들 중, 그 위에 있는 말들이 아닌 그 아래 있는 말들이 빠져나오기 때문에 통과하지 못했다.
    • 따라서 ArrayList타입으로 2차원 배열을 만들어서 for문으로 현재 탐색하는 말의 인덱스를 찾아서 그 위에 있는 말들을 담을 자료구조를 ArrayList타입으로 만들어준다.

✔️ 틀렸던 풀이

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {

    static int N,K,result;
    //                  우 좌 상 하
    static int[] dx = {0,0,0,-1,1};
    static int[] dy = {0,1,-1,0,0};
    static int[][] board;
    static Queue<Integer>[][] q;
    static ArrayList<Horse> hList = new ArrayList<>();
    static class Horse {
        int x,y,d;
        public Horse(int x, int y, int d) {
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }

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

        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());

        board = new int[N][N];
        q = new LinkedList[N][N];
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                q[i][j] = new LinkedList<Integer>();
            }
        }
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<N;j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        for(int i=0;i<K;i++) { // k개의 말 정보 입력
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken())-1;
            int c = Integer.parseInt(st.nextToken())-1;
            int d = Integer.parseInt(st.nextToken());
            hList.add(new Horse(r, c, d));
            q[r][c].add(i);
        } // input end

        result = solve();

        System.out.println(result);
    }

    private static int solve() {
        int turn = 1;
        while(turn <= 1000) {

            // 1. 1번 말부터 k번 말까지 순서대로 이동
            for(int i=0;i<K;i++) {
                // 현재 탐색하는 말의 번호와 상태
                Horse now = hList.get(i);

                int nx = now.x + dx[now.d];
                int ny = now.y + dy[now.d];

                if(isValid(nx, ny)) {
                    moveHorse(nx,ny,i);
                } else { // 이동하려는 칸이 범위를 벗어난 경우 = 파란색의 경우
                    now.d = changeDir(now.d);
                    nx = now.x + dx[now.d];
                    ny = now.y + dy[now.d];
                    if(board[nx][ny] == 2) continue;
                    else moveHorse(nx, ny, i);
                }

                // 2. 4개 이상 쌓이는 순간 게임 종료
                if(q[now.x][now.y].size() >= 4) return turn;
            }


            turn++;
        }

        return -1;
    }

    private static void moveHorse(int nx, int ny, int i) {

        int x = hList.get(i).x;
        int y = hList.get(i).y;

        if(board[nx][ny] == 0) { // 흰색인 경우

            while(!q[x][y].isEmpty()) {
                int temp = q[x][y].poll();
                q[nx][ny].add(temp);
                hList.get(temp).x = nx;
                hList.get(temp).y = ny;
            }

        } else if(board[nx][ny] == 1) { // 빨간색인 경우
            Stack<Integer> stack = new Stack<Integer>();
            int size = q[x][y].size();
            for(int k=0;k<size;k++) {
                stack.add(q[x][y].poll());
            }
            while(!stack.isEmpty()) {
                int temp = stack.pop();
                q[nx][ny].add(temp);
                hList.get(temp).x = nx;
                hList.get(temp).y = ny;
            }

        } else if(board[nx][ny] == 2) { // 파란색인 경우
            hList.get(i).d = changeDir(hList.get(i).d);
            nx = x + dx[hList.get(i).d];
            ny = y + dy[hList.get(i).d];
            if(isValid(nx, ny)&& board[nx][ny] != 2) {
                moveHorse(nx, ny, i);
            }
        }

    }

    private static int changeDir(int dir) {
        if(dir == 1) return 2;
        else if(dir == 2) return 1;
        else if(dir == 3) return 4;
        else return 3;
    }

    private static boolean isValid(int r, int c) {
        if(r<0 || c<0 || r>=N || c>=N) return false;
        return true;
    }

}

✅ 정답 풀이

package algo;

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

public class Main_bj_17837_새로운게임2 {

    static int N,K,result;
    //                  우 좌 상 하
    static int[] dx = {0,0,0,-1,1};
    static int[] dy = {0,1,-1,0,0};
    static int[][] board;
    static ArrayList<Integer>[][] list;
    static ArrayList<Horse> hList = new ArrayList<>();
    static class Horse {
        int x,y,d;
        public Horse(int x, int y, int d) {
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }

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

        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());

        board = new int[N][N];
        list = new ArrayList[N][N];
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                list[i][j] = new ArrayList<Integer>();
            }
        }
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<N;j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        for(int i=0;i<K;i++) { // k개의 말 정보 입력
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken())-1;
            int c = Integer.parseInt(st.nextToken())-1;
            int d = Integer.parseInt(st.nextToken());
            hList.add(new Horse(r, c, d));
            list[r][c].add(i);
        } // input end

        result = solve();

        System.out.println(result);
    }

    private static int solve() {
        int turn = 1;
        while(turn <= 1000) {

            // 1. 1번 말부터 k번 말까지 순서대로 이동
            for(int i=0;i<K;i++) {
                // 현재 탐색하는 말의 번호와 상태
                Horse now = hList.get(i);
                ArrayList<Integer> up_horse = new ArrayList<>();
                int start_idx = 0;
                int x = now.x;
                int y = now.y;

                for(int p=0;p<list[x][y].size();p++) {
                    if(list[x][y].get(p) == i) {
                        start_idx = p;
                        break;
                    }
                }

                for(int p=start_idx;p<list[x][y].size();p++) {
                    up_horse.add(list[x][y].get(p));
                }

                int nx = now.x + dx[now.d];
                int ny = now.y + dy[now.d];

                if(!isValid(nx, ny) || board[nx][ny] == 2) {
                    hList.get(i).d = changeDir(hList.get(i).d);
                    nx = now.x + dx[hList.get(i).d];
                    ny = now.y + dy[hList.get(i).d];
                    if(!isValid(nx, ny) || board[nx][ny] == 2) continue;
                    else {
                        if(board[nx][ny] == 0) {
                            for(int h : up_horse) {
                                list[nx][ny].add(h);
                                hList.get(h).x = nx;
                                hList.get(h).y = ny;
                            }
                        }
                        else if(board[nx][ny] == 1) {
                            for(int p=up_horse.size()-1;p>=0;p--) {
                                list[nx][ny].add(up_horse.get(p));
                                hList.get(up_horse.get(p)).x = nx;
                                hList.get(up_horse.get(p)).y = ny;
                            }
                        }
                    }
                }
                else if(board[nx][ny] == 0) {
                    for(int h : up_horse) {
                        list[nx][ny].add(h);
                        hList.get(h).x = nx;
                        hList.get(h).y = ny;
                    }
                }
                else if(board[nx][ny] == 1) {
                    for(int p=up_horse.size()-1;p>=0;p--) {
                        list[nx][ny].add(up_horse.get(p));
                        hList.get(up_horse.get(p)).x = nx;
                        hList.get(up_horse.get(p)).y = ny;
                    }
                }

                // 2. 4개 이상 쌓이는 순간 게임 종료
                if(list[now.x][now.y].size() >= 4) return turn;

                for(int p=list[x][y].size()-1;p>=start_idx;p--) {
                    list[x][y].remove(p);
                }
            }


            turn++;
        }

        return -1;
    }

    private static int changeDir(int dir) {
        if(dir == 1) return 2;
        else if(dir == 2) return 1;
        else if(dir == 3) return 4;
        else return 3;
    }

    private static boolean isValid(int r, int c) {
        if(r<0 || c<0 || r>=N || c>=N) return false;
        return true;
    }

}