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

4 분 소요

문제 링크

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


풀이 과정

문제에서 요구하는 바를 그대로 따라 구현하는 시뮬레이션 문제입니다.

문제를 풀면서 제가 빠뜨렸던 조건들은 다음과 같습니다.

  1. 말이 이동하려는 칸이 흰색, 빨간색일 경우 같이 이동하는 말들이 있으므로, 이동하는 모든 말들의 현재 좌표를 바꿔주지 않음.
  2. 이동하려는 칸이 파란색일 경우, 말의 이동 방향을 설정하는 과정을 조건부로 했음. 어느 조건에서는 이동 방향 설정을 하지 않은 채 움직임.

board = new String[N + 1][N + 1];

for (int i = 1; i <= N; i++) {
    Arrays.fill(board[i], "");
}

말이 이동할 때 위에 올려져 있는 말도 함께 이동하기 때문에, 이어 붙이기와 부분 자르기가 가능한 문자열 배열을 사용했습니다. 문자열 배열은 기본적으로 null 로 초기화 됩니다. 만약, 공백 문자로 다시 초기화하지 않을 경우, 이후 += 연산을 하면 n,u,l,l 을 이어 붙인 문자열 null 이 되므로 유의해야 했습니다.


color = new int[N + 1][N + 1];

for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
        color[i][j] = sc.nextInt();
    }
}

color 배열에는 입력받은 칸의 색 정보가 저장됩니다.


for (int i = 0; i < K; i++) {
    marker[i][0] = sc.nextInt();
    marker[i][1] = sc.nextInt();
    marker[i][2] = sc.nextInt();

    board[marker[i][0]][marker[i][1]] = Integer.toString(i);
}

marker 배열은 말의 정보를 저장하는 배열입니다. 0번 인덱스에는 , 1번 인덱스에는 , 2번 인덱스에는 이동 방향을 저장합니다. 또한, board 배열에 초기 말의 인덱스를 문자열로 변환해 저장합니다.


while (++turn <= 1000) {
    for (int i = 0; i < K; i++) {
        int now_i = marker[i][0];
        int now_j = marker[i][1];
        int now_dir = marker[i][2];

        int next_i = now_i + di[now_dir];
        int next_j = now_j + dj[now_dir];

        if (!check(next_i, next_j) || color[next_i][next_j] == 2) {
            marker[i][2] = now_dir = changeDirection(now_dir);

            int next_next_i = now_i + di[now_dir];
            int next_next_j = now_j + dj[now_dir];

            if (check(next_next_i, next_next_j) && color[next_next_i][next_next_j] != 2) {
                move(i, now_i, now_j, next_next_i, next_next_j);
            }
        }

        else {
            move(i, now_i, now_j, next_i, next_j);
        }
    }

    if (exit) break;
}

천 번동안 턴을 증가시키며 말들을 순차적으로 이동시킵니다.


if (!check(next_i, next_j) || color[next_i][next_j] == 2) {
    marker[i][2] = now_dir = changeDirection(now_dir);

    int next_next_i = now_i + di[now_dir];
    int next_next_j = now_j + dj[now_dir];

    if (check(next_next_i, next_next_j) && color[next_next_i][next_next_j] != 2) {
        move(i, now_i, now_j, next_next_i, next_next_j);
    }
}

말이 이동하려는 칸이 체스판을 벗어나거나, 파란색 칸인 경우, changeDirection 메소드를 통해 이동 방향을 변경하고, 변경된 이동 방향을 marker[i][2] 에 갱신합니다. 이동 방향을 변경하고 나서는 문제 조건에 따라 한 칸을 더 이동시킵니다. 대신, 이동하려는 칸이 체스판을 벗어나거나, 파란색 칸이면 이동하지 않습니다.


else {
    move(i, now_i, now_j, next_i, next_j);
}

말이 이동하려는 칸이 체스판을 벗어나지도, 파란색도 아닌 경우, move 메소드를 호출해 한 칸 이동을 합니다.


private static void move(int k, int now_i, int now_j, int next_i, int next_j) {
    int beginIndex = board[now_i][now_j].indexOf(Integer.toString(k));

    for (int i = beginIndex; i < board[now_i][now_j].length(); i++) {
        int num = Integer.parseInt(String.valueOf(board[now_i][now_j].charAt(i)));

        marker[num][0] = next_i;
        marker[num][1] = next_j;
    }

    if (color[next_i][next_j] == 0) {
        board[next_i][next_j] += board[now_i][now_j].substring(beginIndex);
    }

    else if (color[next_i][next_j] == 1) {
        StringBuilder sb = new StringBuilder(board[now_i][now_j].substring(beginIndex));
        board[next_i][next_j] += sb.reverse();
    }

    board[now_i][now_j] = board[now_i][now_j].substring(0, beginIndex);

    if (board[next_i][next_j].length() >= 4) {
        exit = true;
    }
}

위는 move 메소드 입니다. 현재 말 번호(k), 현재 말의 좌표(now_i, now_j), 이동하려는 칸의 좌표(next_i, next_j) 를 파라미터로 받습니다. 체스판내 말이 위치하는 좌표에서 말 번호를 통해 말의 위치( beginIndex ) 를 찾습니다. 이후, 해당 말을 기준으로 위에 있는 말들의 좌표들을 이동하려는 칸의 좌표로 모두 바꿔줍니다.

이동하려는 칸이 흰 색인 경우 += 연산을 통해 맨 위에 올려 놓고, 빨간색인 경우는 reverse 메소드를 호출해뒤집고 난 뒤 += 연산을 통해 맨 위에 올려 놓습니다.

원래 좌표에 존재했던 말들은 제거하고, 이동한 칸의 말의 개수를 세어, 그 개수가 4개 이상이면 종료합니다.


코드

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int N, K;
    static int[][] color;
    static int[][] marker;
    static String[][] board;

    static int[] di = {0, 0, 0, -1, 1};
    static int[] dj = {0, 1, -1, 0, 0};

    static boolean exit;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        K = sc.nextInt();
        color = new int[N + 1][N + 1];
        marker = new int[K][3];
        board = new String[N + 1][N + 1];

        for (int i = 1; i <= N; i++) {
            Arrays.fill(board[i], "");
        }

        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                color[i][j] = sc.nextInt();
            }
        }

        for (int i = 0; i < K; i++) {
            marker[i][0] = sc.nextInt();
            marker[i][1] = sc.nextInt();
            marker[i][2] = sc.nextInt();

            board[marker[i][0]][marker[i][1]] = Integer.toString(i);
        }

        int turn = 0;

        while (++turn <= 1000) {
            for (int i = 0; i < K; i++) {
                int now_i = marker[i][0];
                int now_j = marker[i][1];
                int now_dir = marker[i][2];

                int next_i = now_i + di[now_dir];
                int next_j = now_j + dj[now_dir];

                if (!check(next_i, next_j) || color[next_i][next_j] == 2) {
                    marker[i][2] = now_dir = changeDirection(now_dir);

                    int next_next_i = now_i + di[now_dir];
                    int next_next_j = now_j + dj[now_dir];

                    if (check(next_next_i, next_next_j) && color[next_next_i][next_next_j] != 2) {
                        move(i, now_i, now_j, next_next_i, next_next_j);
                    }
                }

                else {
                    move(i, now_i, now_j, next_i, next_j);
                }
            }

            if (exit) break;
        }

        System.out.println(exit ? turn : -1);
    }

    private static void move(int k, int now_i, int now_j, int next_i, int next_j) {
        int beginIndex = board[now_i][now_j].indexOf(Integer.toString(k));

        for (int i = beginIndex; i < board[now_i][now_j].length(); i++) {
            int num = Integer.parseInt(String.valueOf(board[now_i][now_j].charAt(i)));

            marker[num][0] = next_i;
            marker[num][1] = next_j;
        }

        if (color[next_i][next_j] == 0) {
            board[next_i][next_j] += board[now_i][now_j].substring(beginIndex);
        }

        else if (color[next_i][next_j] == 1) {
            StringBuilder sb = new StringBuilder(board[now_i][now_j].substring(beginIndex));
            board[next_i][next_j] += sb.reverse();
        }

        board[now_i][now_j] = board[now_i][now_j].substring(0, beginIndex);

        if (board[next_i][next_j].length() >= 4) {
            exit = true;
        }
    }

    private static boolean check(int i, int j) {
        if (i < 1 || i > N || j < 1 || j > N) return false;
        return true;
    }

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

카테고리:

업데이트:

댓글남기기